Issue | Instances | |
---|---|---|
GAS-1 | Using bools for storage incurs overhead | 4 |
GAS-2 | Cache array length outside of loop | 6 |
GAS-3 | Use calldata instead of memory for function arguments that do not get mutated | 1 |
GAS-4 | For Operations that will not overflow, you could use unchecked | 287 |
GAS-5 | Use Custom Errors | 6 |
GAS-6 | Don't initialize variables with default value | 13 |
GAS-7 | Functions guaranteed to revert when called by normal users can be marked payable |
19 |
GAS-8 | ++i costs less gas than i++ , especially when it's used in for -loops (--i /i-- too) |
15 |
GAS-9 | Using private rather than public for constants, saves gas |
1 |
GAS-10 | Use shift Right/Left instead of division/multiplication if possible | 1 |
GAS-11 | Use != 0 instead of > 0 for unsigned integer comparison | 8 |
Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from ‘false’ to ‘true’, after having been ‘true’ in the past. See source.
Instances (4):
File: pools/Omnipool.sol
48: bool public isShutdown;
49: bool public desactivated;
50: bool public rebalancingRewardActive;
File: tokenomics/GaugeFactory.sol
14: mapping(address => bool) public isFactoryGauge;
If not cached, the solidity compiler will always read the length of the array during each iteration. That is, if it is a storage array, this is an extra sload operation (100 additional extra gas for each iteration except for the first) and if it is a memory array, this is an extra mload operation (3 additional gas for each iteration except for the first).
Instances (6):
File: pools/Omnipool.sol
471: for (uint256 i; i < allocatedPerPool.length; i++) {
559: for (uint256 i; i < allocatedPerPool.length; i++) {
File: pools/OmnipoolController.sol
253: for (uint256 i; i < pools.length; i++) {
268: for (uint256 i; i < pools.length; i++) {
272: for (uint256 i; i < pools.length; i++) {
290: for (uint256 i; i < pools.length; i++) {
Mark data types as calldata
instead of memory
where possible. This makes it so that the data is not automatically loaded into memory. If the data passed into the function does not need to be changed (like updating values in an array), it can be passed in as calldata
. The one exception to this is if the argument must later be passed into another function that takes an argument that specifies memory
storage.
Instances (1):
File: tokenomics/GaugeController.sol
611: function addType(string memory name, uint256 weight) external nonReentrant onlyOpalTeam {
Instances (287):
File: pools/BPTOracle.sol
77: ++i;
77: ++i;
88: ++i;
88: ++i;
91: return (min * IRateProvider(poolAddress).getRate()) / 1e18;
91: return (min * IRateProvider(poolAddress).getRate()) / 1e18;
127: ++i;
127: ++i;
160: ++i;
160: ++i;
171: uint256 actualPrice = assetPrice * poolRate / poolRate;
171: uint256 actualPrice = assetPrice * poolRate / poolRate;
176: ++i;
176: ++i;
180: uint256 priceResult = minPrice * poolRate;
182: return priceResult / 1e18;
215: if (updatedAt + tokenHeartbeat[token] < block.timestamp) revert StalePrice();
229: price = _price / (10 ** (_answerDigits - targetDigits));
229: price = _price / (10 ** (_answerDigits - targetDigits));
229: price = _price / (10 ** (_answerDigits - targetDigits));
229: price = _price / (10 ** (_answerDigits - targetDigits));
232: price = _price * (10 ** (targetDigits - _answerDigits));
232: price = _price * (10 ** (targetDigits - _answerDigits));
232: price = _price * (10 ** (targetDigits - _answerDigits));
232: price = _price * (10 ** (targetDigits - _answerDigits));
244: return amount * getUSDPrice(token) / 1e18;
244: return amount * getUSDPrice(token) / 1e18;
File: pools/Omnipool.sol
38: UnderlyingPool[] public underlyingPools; // slice of all balancer underlying pools
38: UnderlyingPool[] public underlyingPools; // slice of all balancer underlying pools
42: uint256 public totalDeposited; // total amount of deposit tokens deposited
42: uint256 public totalDeposited; // total amount of deposit tokens deposited
43: uint256 public totalUnderlyingPools; // total number of underlying balancer pools
43: uint256 public totalUnderlyingPools; // total number of underlying balancer pools
143: uint256 bptValue = bptPrice * bptBalance / 1e18;
143: uint256 bptValue = bptPrice * bptBalance / 1e18;
155: totalTvl += getPoolTvl(i);
157: ++i;
157: ++i;
222: uint256 underlyingBalanceIncrease = afterTotalUnderlying - beforeTotalUnderlying;
229: totalDeposited += _amountIn;
269: ++i;
269: ++i;
285: ++totalUnderlyingPools;
285: ++totalUnderlyingPools;
331: uint256 underlyingToWithdraw_ = underlyingToReceive_ - underlyingBalanceBefore_;
337: uint256 underlyingFees = underlyingWithdrawn_ * WITHDRAW_FEES / SCALED_ONE;
337: uint256 underlyingFees = underlyingWithdrawn_ * WITHDRAW_FEES / SCALED_ONE;
338: underlyingWithdrawn_ -= underlyingFees;
345: totalDeposited -= underlyingWithdrawn_;
380: return valuation * bptBalance;
401: userDataAmountsIn = new uint256[](_pool.assets.length - 1);
402: userDataAmountsIn[_pool.assetIndex - 1] = _underlyingAmountIn;
439: uint256 totalAfterDeposit = totalUnderlying_ + _underlyingAmountIn;
446: if (depositsRemaining < maxDeposit + 1e2) {
455: depositsRemaining -= toDeposit;
456: allocatedPerPoolCopy[poolIndex] += toDeposit;
470: int256 depositPoolIndex = -1;
471: for (uint256 i; i < allocatedPerPool.length; i++) {
471: for (uint256 i; i < allocatedPerPool.length; i++) {
478: uint256 maxBalance_ = targetAllocation_ + targetAllocation_.mulDown(_getMaxDeviation());
479: uint256 maxDepositAmount_ = maxBalance_ - currentAlloc;
484: require(depositPoolIndex > -1, "error retrieving deposit pool");
513: assetIndex = assetIndex - 1;
533: uint256 totalAfterWithdrawal = totalUnderlying_ - underlyingToWithdraw_;
540: if (withdrawalsRemaining < maxWithdrawal + 1e2) {
548: withdrawalsRemaining -= underlyingToWithdraw;
549: allocatedPerPoolCopy[poolIndex] -= underlyingToWithdraw;
558: int256 withdrawPoolIndex = -1;
559: for (uint256 i; i < allocatedPerPool.length; i++) {
559: for (uint256 i; i < allocatedPerPool.length; i++) {
568: uint256 allocatedUsd = (price_ * currentAlloc) / 10 ** underlyingToken.decimals();
568: uint256 allocatedUsd = (price_ * currentAlloc) / 10 ** underlyingToken.decimals();
568: uint256 allocatedUsd = (price_ * currentAlloc) / 10 ** underlyingToken.decimals();
568: uint256 allocatedUsd = (price_ * currentAlloc) / 10 ** underlyingToken.decimals();
569: if (allocatedUsd >= _MAX_USD_LP_VALUE_FOR_REMOVING_CURVE_POOL / 2) {
576: uint256 minBalance_ = targetAllocation_ - targetAllocation_.mulDown(_getMaxDeviation());
577: uint256 maxWithdrawAmount_ = currentAlloc - minBalance_;
582: require(withdrawPoolIndex > -1, "error retrieving withdraw pool");
617: total += getUserDeposit(user, i);
619: ++i;
619: ++i;
640: if (lpSupply == 0 || totalUnderlying_ == 0) return 10 ** 18;
640: if (lpSupply == 0 || totalUnderlying_ == 0) return 10 ** 18;
653: return poolTvl == 0 || totalTvl == 0 ? 0 : (poolTvl * 100 / totalTvl);
653: return poolTvl == 0 || totalTvl == 0 ? 0 : (poolTvl * 100 / totalTvl);
674: totalUnderlying_ += poolUnderlying;
676: ++i;
676: ++i;
679: totalAllocated = totalUnderlying_ + underlyingToken.balanceOf(address(this));
693: int256 diff = int256(underlyingPools[i].targetWeight) - int256(currentPoolWeight);
699: ++i;
699: ++i;
791: uint256 deadline = block.timestamp + 60_000;
854: ++i;
854: ++i;
868: int256 scaleUp_ = int256(ScaledMath.ONE.divDown(ScaledMath.ONE - pool.targetWeight));
878: ++i;
878: ++i;
911: totalDeviation += targetAmount.absSub(perPoolAllocations_[i]);
913: ++i;
913: ++i;
952: total += newWeight;
954: ++i;
954: ++i;
1044: ++i;
1044: ++i;
1063: ++i;
1063: ++i;
1097: ++i;
1097: ++i;
1110: ++i;
1110: ++i;
1122: ++i;
1122: ++i;
File: pools/OmnipoolController.sol
185: ++i;
185: ++i;
202: ++i;
202: ++i;
239: ++i;
239: ++i;
253: for (uint256 i; i < pools.length; i++) {
253: for (uint256 i; i < pools.length; i++) {
261: totalUSDValue += poolUSDValue;
268: for (uint256 i; i < pools.length; i++) {
268: for (uint256 i; i < pools.length; i++) {
269: poolWeights[i] = ScaledMath.ONE / pools.length;
272: for (uint256 i; i < pools.length; i++) {
272: for (uint256 i; i < pools.length; i++) {
290: for (uint256 i; i < pools.length; i++) {
290: for (uint256 i; i < pools.length; i++) {
298: totalUSDValue += usdValue;
307: totalUSDValue == 0 ? ScaledMath.ONE / pools.length : poolUSDValue.divDown(totalUSDValue);
File: tokenomics/EscrowedToken.sol
36: uint256 public vestingDuration = WEEK * 8;
87: function transfer(address, /*to*/ uint256 /*amount*/ )
87: function transfer(address, /*to*/ uint256 /*amount*/ )
87: function transfer(address, /*to*/ uint256 /*amount*/ )
87: function transfer(address, /*to*/ uint256 /*amount*/ )
87: function transfer(address, /*to*/ uint256 /*amount*/ )
87: function transfer(address, /*to*/ uint256 /*amount*/ )
87: function transfer(address, /*to*/ uint256 /*amount*/ )
87: function transfer(address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
102: function transferFrom(address, /*from*/ address, /*to*/ uint256 /*amount*/ )
132: activeCount++;
132: activeCount++;
135: ++i;
135: ++i;
145: ++index;
145: ++index;
149: ++i;
149: ++i;
174: remainingTime = userVesting.end - block.timestamp;
178: userVesting.amount * (SCALED_ONE + (ratePerToken - userVesting.ratePerToken))
178: userVesting.amount * (SCALED_ONE + (ratePerToken - userVesting.ratePerToken))
178: userVesting.amount * (SCALED_ONE + (ratePerToken - userVesting.ratePerToken))
179: ) / SCALED_ONE;
182: uint256 removedAmount = (claimAmount * remainingTime) / vestingDuration;
182: uint256 removedAmount = (claimAmount * remainingTime) / vestingDuration;
183: claimAmount -= removedAmount;
206: uint256 vestingEnd = startTimestamp + vestingDuration;
217: userVestingCount[receiver]++;
217: userVestingCount[receiver]++;
219: totalVesting += amount;
244: i++;
244: i++;
254: for (uint256 i; i < userNextIndex; i++) {
254: for (uint256 i; i < userNextIndex; i++) {
274: remainingTime = userVesting.end - block.timestamp;
277: userVesting.amount * (SCALED_ONE + (ratePerToken - userVesting.ratePerToken))
277: userVesting.amount * (SCALED_ONE + (ratePerToken - userVesting.ratePerToken))
277: userVesting.amount * (SCALED_ONE + (ratePerToken - userVesting.ratePerToken))
278: ) / SCALED_ONE;
279: uint256 removedAmount = (claimAmount * remainingTime) / vestingDuration;
279: uint256 removedAmount = (claimAmount * remainingTime) / vestingDuration;
280: claimAmount -= removedAmount;
283: totalVesting -= userVesting.amount;
288: ratePerToken += (SCALED_ONE * removedAmount) / totalVesting;
288: ratePerToken += (SCALED_ONE * removedAmount) / totalVesting;
288: ratePerToken += (SCALED_ONE * removedAmount) / totalVesting;
File: tokenomics/GaugeController.sol
9: uint256 public constant WEIGHT_VOTE_DELAY = 10 * 86_400; // 10 days
9: uint256 public constant WEIGHT_VOTE_DELAY = 10 * 86_400; // 10 days
9: uint256 public constant WEIGHT_VOTE_DELAY = 10 * 86_400; // 10 days
52: mapping(address => uint256) public lastGaugeUpdate; // last scheduled time (next week)
52: mapping(address => uint256) public lastGaugeUpdate; // last scheduled time (next week)
58: mapping(int128 => uint256) public lastTypeUpdate; // last scheduled time (next week)
58: mapping(int128 => uint256) public lastTypeUpdate; // last scheduled time (next week)
61: uint256 public lastUpdate; // last scheduled time (next week)
61: uint256 public lastUpdate; // last scheduled time (next week)
65: mapping(int128 => uint256) public lastTypeWeightUpdate; // last scheduled time (next week)
65: mapping(int128 => uint256) public lastTypeWeightUpdate; // last scheduled time (next week)
102: lastUpdate = (block.timestamp / WEEK) * WEEK;
102: lastUpdate = (block.timestamp / WEEK) * WEEK;
114: return gaugeTypes[_gauge] - 1;
224: ++i;
224: ++i;
243: timestamp += WEEK;
252: ++i;
252: ++i;
271: timestamp += WEEK;
278: votes -= voteChanges;
288: ++i;
288: ++i;
309: ++i;
309: ++i;
317: timestamp += WEEK;
324: votesTotal += typeVoteChange * typeWeight;
324: votesTotal += typeVoteChange * typeWeight;
327: ++k;
327: ++k;
338: ++j;
338: ++j;
357: timestamp += WEEK;
364: votes -= voteChanges;
374: ++i;
374: ++i;
392: timestamp = (timestamp / WEEK) * WEEK;
392: timestamp = (timestamp / WEEK) * WEEK;
397: int128 gaugeType = gaugeTypes[gauge] - 1;
400: return SCALED_ONE * typeWeight * gaugeWeight / totalWeight;
400: return SCALED_ONE * typeWeight * gaugeWeight / totalWeight;
400: return SCALED_ONE * typeWeight * gaugeWeight / totalWeight;
412: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
412: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
412: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
414: totalWeight += (oldSum * weight) - (oldSum * oldWeight);
414: totalWeight += (oldSum * weight) - (oldSum * oldWeight);
414: totalWeight += (oldSum * weight) - (oldSum * oldWeight);
414: totalWeight += (oldSum * weight) - (oldSum * oldWeight);
431: int128 gaugeType = gaugeTypes[gauge] - 1;
436: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
436: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
436: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
441: uint256 newSum = oldSum + (weight - oldGaugeWeight);
441: uint256 newSum = oldSum + (weight - oldGaugeWeight);
442: totalWeight += (oldSum * weight) - (oldSum * typeWeight);
442: totalWeight += (oldSum * weight) - (oldSum * typeWeight);
442: totalWeight += (oldSum * weight) - (oldSum * typeWeight);
442: totalWeight += (oldSum * weight) - (oldSum * typeWeight);
475: vars.nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
475: vars.nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
475: vars.nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
476: if (locks[vars.len - 1].unlockTime < vars.nextTimestamp) revert NoActiveLocks();
478: if (block.timestamp < lastUserVote[user][gauge] + WEIGHT_VOTE_DELAY) revert VoteCooldown();
485: uint256 i = vars.len - 1;
488: uint256 weightedAmount = currentLock.amount * voteWeight / 10_000;
488: uint256 weightedAmount = currentLock.amount * voteWeight / 10_000;
489: newUserVote.amount += weightedAmount;
497: i--;
497: i--;
504: vars.gaugeType = gaugeTypes[gauge] - 1;
510: vars.powerUsed = vars.powerUsed + voteWeight - lastVote.weight;
510: vars.powerUsed = vars.powerUsed + voteWeight - lastVote.weight;
522: for (uint256 j; j < vars.oldUnlocksLen; j++) {
522: for (uint256 j; j < vars.oldUnlocksLen; j++) {
526: gaugeVoteChanges[gauge][oldUnlocks[j].unlockTime] -= oldUnlocks[j].amount;
527: typeVoteChanges[vars.gaugeType][oldUnlocks[j].unlockTime] -= oldUnlocks[j].amount;
531: vars.oldGaugeWeight -= oldUnlocks[j].amount;
532: vars.oldSum -= oldUnlocks[j].amount;
535: gaugeVotes[gauge][vars.nextTimestamp] = vars.oldGaugeWeight + newUserVote.amount;
536: typeVotes[vars.gaugeType][vars.nextTimestamp] = vars.oldSum + newUserVote.amount;
538: for (uint256 k; k < vars.len; k++) {
538: for (uint256 k; k < vars.len; k++) {
542: gaugeVoteChanges[gauge][unlocks[k].unlockTime] += unlocks[k].amount;
543: typeVoteChanges[vars.gaugeType][unlocks[k].unlockTime] += unlocks[k].amount;
552: for (uint256 l; l < vars.len; l++) {
552: for (uint256 l; l < vars.len; l++) {
579: numberGauges++;
579: numberGauges++;
582: gaugeTypes[gauge] = gaugeType + 1;
583: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
583: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
583: uint256 nextTimestamp = ((block.timestamp + WEEK) / WEEK) * WEEK;
590: typeVotes[gaugeType][nextTimestamp] = oldSum + weight;
592: totalVotes[nextTimestamp] = olTotal + (weight * typeWeight);
592: totalVotes[nextTimestamp] = olTotal + (weight * typeWeight);
613: numberGaugeTypes++;
613: numberGaugeTypes++;
Source Instead of using error strings, to reduce deployment and runtime cost, you should use Custom Errors. This would save both deployment and runtime cost.
Instances (6):
File: pools/Omnipool.sol
225: require(lpReceived >= _minLpReceived, "too much slippage");
484: require(depositPoolIndex > -1, "error retrieving deposit pool");
506: require(balance >= _bptAmountOut, "not enough balance");
582: require(withdrawPoolIndex > -1, "error retrieving withdraw pool");
863: if (weight_ == 0) revert("pool already set to 0 weight");
865: revert("can't remove last pool");
Instances (13):
File: pools/BPTOracle.sol
114: for (uint256 i = 0; i < length;) {
File: pools/Omnipool.sol
154: for (uint8 i = 0; i < len;) {
266: for (uint256 i = 0; i < length;) {
616: for (uint8 i = 0; i < length;) {
670: for (uint8 i = 0; i < length;) {
688: uint8 min = 0;
689: int256 largestDiff = 0;
691: for (uint8 i = 0; i < length;) {
849: for (uint8 i = 0; i < length;) {
1058: for (uint8 i = 0; i < len;) {
1092: for (uint8 i = 0; i < length;) {
1105: for (uint8 i = 0; i < length;) {
1119: for (uint8 i = 0; i < length;) {
If a function modifier such as onlyOwner
is used, the function will revert if a normal user tries to pay the function. Marking the function as payable
will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided.
Instances (19):
File: pools/BPTOracle.sol
55: function setHeartbeat(address token, uint256 heartbeat) external onlyOpalTeam {
File: pools/Omnipool.sol
167: function setRewardManager(address _rewardManager) external onlyOpalTeam {
590: function setMaxDeviation(uint256 _maxDeviation) external onlyOpalTeam {
710: function approveForRewardManager(address token, uint256 amount) external onlyRewardManager {
719: function setExtraRewardPool(address _token, bytes32 _poolId) external onlyOpalTeam {
731: function setGemPoolId(bytes32 _poolId) external onlyOpalTeam {
834: function desactivate() external onlyController {
File: pools/OmnipoolController.sol
85: function addOmnipool(address poolAddress) external onlyOpalTeam {
100: function removePool(address poolAddress) external onlyOpalTeam {
112: function addRebalancingRewardHandler(address pool, address handler) external onlyOpalTeam {
120: function removeBalanceHandler(address pool, address handler) external onlyOpalTeam {
133: function addPoolToOmnipool(address balancerPool, address omnipool_) external onlyOpalTeam {
146: function desactivatePool(address poolAddress) external onlyOpalTeam {
212: function setWeightUpdateMinDelay(uint256 delay) external onlyOpalTeam {
File: pools/OpalLpToken.sol
46: function mint(address to, uint256 amount) public override onlyMinter returns (uint256) {
58: function burn(address _owner, uint256 _amount) external override onlyBurner returns (uint256) {
File: tokenomics/GaugeController.sol
611: function addType(string memory name, uint256 weight) external nonReentrant onlyOpalTeam {
636: function changeGaugeWeight(address gauge, uint256 weight) external nonReentrant onlyOpalTeam {
File: tokenomics/GaugeFactory.sol
74: function setImplementation(address _implementation) external onlyOpalTeam {
Saves 5 gas per loop
Instances (15):
File: pools/Omnipool.sol
471: for (uint256 i; i < allocatedPerPool.length; i++) {
559: for (uint256 i; i < allocatedPerPool.length; i++) {
File: pools/OmnipoolController.sol
253: for (uint256 i; i < pools.length; i++) {
268: for (uint256 i; i < pools.length; i++) {
272: for (uint256 i; i < pools.length; i++) {
290: for (uint256 i; i < pools.length; i++) {
File: tokenomics/EscrowedToken.sol
132: activeCount++;
217: userVestingCount[receiver]++;
244: i++;
254: for (uint256 i; i < userNextIndex; i++) {
File: tokenomics/GaugeController.sol
522: for (uint256 j; j < vars.oldUnlocksLen; j++) {
538: for (uint256 k; k < vars.len; k++) {
552: for (uint256 l; l < vars.len; l++) {
579: numberGauges++;
613: numberGaugeTypes++;
If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table
Instances (1):
File: tokenomics/GaugeController.sol
9: uint256 public constant WEIGHT_VOTE_DELAY = 10 * 86_400; // 10 days
Instances (1):
File: pools/Omnipool.sol
569: if (allocatedUsd >= _MAX_USD_LP_VALUE_FOR_REMOVING_CURVE_POOL / 2) {
Instances (8):
File: pools/Omnipool.sol
400: if (_pool.bptIndex > 0) {
442: while (depositsRemaining > 0) {
512: if (_pool.bptIndex > 0 && _pool.bptIndex < assetIndex) {
536: while (withdrawalsRemaining > 0) {
File: tokenomics/EscrowedToken.sol
287: if (totalVesting > 0) {
File: tokenomics/GaugeController.sol
2: pragma solidity >=0.8.16;
496: if (i > 0) {
585: if (weight > 0) {
Issue | Instances | |
---|---|---|
NC-1 | Event is missing indexed fields |
5 |
Index 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 (5):
File: tokenomics/GaugeController.sol
69: event AddType(string name, int128 typeId);
70: event NewGauge(address gauge, int128 gaugeType, uint256 weight);
71: event NewTypeWeight(int128 typeId, uint256 time, uint256 weight, uint256 totalWeight);
72: event NewGaugeWeight(address gauge, uint256 time, uint256 weight, uint256 totalWeight);
73: event VoteForGauge(uint256 time, address user, address gauge, uint256 weight);
Issue | Instances | |
---|---|---|
L-1 | Initializers could be front-run | 1 |
L-2 | Unspecific compiler version pragma | 1 |
Initializers could be front-run, allowing an attacker to either set their own values, take ownership of the contract, and in the best case forcing a re-deployment
Instances (1):
File: tokenomics/GaugeFactory.sol
56: ILiquidityGauge(gauge).initialize(lpToken);
Instances (1):
File: tokenomics/GaugeController.sol
2: pragma solidity >=0.8.16;