Issue | Instances | |
---|---|---|
GAS-1 | Using bools for storage incurs overhead | 17 |
GAS-2 | Cache array length outside of loop | 18 |
GAS-3 | Use Custom Errors | 202 |
GAS-4 | Don't initialize variables with default value | 66 |
GAS-5 | Long revert strings | 36 |
GAS-6 | Functions guaranteed to revert when called by normal users can be marked payable |
16 |
GAS-7 | ++i costs less gas than i++ , especially when it's used in for -loops (--i /i-- too) |
21 |
GAS-8 | Using private rather than public for constants, saves gas |
38 |
GAS-9 | Use shift Right/Left instead of division/multiplication if possible | 5 |
GAS-10 | Use != 0 instead of > 0 for unsigned integer comparison | 96 |
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 (17):
File: mixins/Auth.sol
42: bool public paused;
File: p1/BasketHandler.sol
139: bool private disabled;
File: p1/Broker.sol
41: bool public disabled;
44: mapping(address => bool) private trades;
File: plugins/mocks/BadCollateralPlugin.sol
10: bool public checkSoftDefault = true; // peg
11: bool public checkHardDefault = true; // defi invariant
File: plugins/mocks/BadERC20.sol
13: bool public revertDecimals;
15: mapping(address => bool) public censored;
File: plugins/mocks/ERC1271Mock.sol
14: bool public approvalsOn = false;
File: plugins/mocks/GnosisMockReentrant.sol
16: bool public reenterOnInit;
17: bool public reenterOnSettle;
File: plugins/mocks/InvalidBrokerMock.sol
20: mapping(address => bool) private trades;
24: bool public disabled = false;
File: plugins/mocks/InvalidChainlinkMock.sol
13: bool public simplyRevert;
File: plugins/mocks/InvalidFiatCollateral.sol
9: bool public simplyRevert;
File: plugins/mocks/RTokenCollateral.sol
31: bool public priceable;
File: plugins/mocks/UnpricedAssetPlugin.sol
13: bool public unpriced = false;
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 (18):
File: libraries/String.sol
14: for (uint256 i = 0; i < bStr.length; i++) {
File: p1/BasketHandler.sol
218: for (uint256 i = 0; i < config.erc20s.length; ++i) {
227: for (uint256 i = 0; i < erc20s.length; ++i) {
262: for (uint256 i = 0; i < erc20s.length; ++i) {
653: for (uint256 i = 0; i < erc20s.length; i++) {
707: for (uint256 i = 0; i < erc20s.length; ++i) {
725: for (uint256 i = 0; i < erc20s.length; ++i) {
File: p1/Distributor.sol
108: for (uint256 i = 0; i < destinations.length(); ++i) {
File: p1/RToken.sol
270: for (uint256 i = 0; i < erc20s.length; ++i) {
711: for (uint256 i = 0; i < queue.tokens.length; ++i) {
File: p1/mixins/RecollateralizationLib.sol
242: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
329: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
File: p1/mixins/RewardableLib.sol
27: for (uint256 i = 0; i < registry.assets.length; ++i) {
File: plugins/mocks/EasyAuction.sol
277: for (uint256 i = 0; i < _minBuyAmounts.length; i++) {
288: for (uint256 i = 0; i < _minBuyAmounts.length; i++) {
316: for (uint256 i = 0; i < _sellOrders.length; i++) {
513: for (uint256 i = 0; i < orders.length; i++) {
524: for (uint256 i = 0; i < orders.length; i++) {
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 (202):
File: libraries/RedemptionBattery.sol
44: require(amount <= charge, "redemption battery insufficient");
File: mixins/Auth.sol
94: require(account != address(0), "cannot grant role to address 0");
181: require(shortFreeze_ > 0 && shortFreeze_ <= MAX_SHORT_FREEZE, "short freeze out of range");
188: require(longFreeze_ > 0 && longFreeze_ <= MAX_LONG_FREEZE, "long freeze out of range");
197: require(newUnfreezeAt > unfreezeAt, "frozen");
File: mixins/ComponentRegistry.sol
37: require(address(val) != address(0), "invalid RToken address");
45: require(address(val) != address(0), "invalid StRSR address");
53: require(address(val) != address(0), "invalid AssetRegistry address");
61: require(address(val) != address(0), "invalid BasketHandler address");
69: require(address(val) != address(0), "invalid BackingManager address");
77: require(address(val) != address(0), "invalid Distributor address");
85: require(address(val) != address(0), "invalid RSRTrader address");
93: require(address(val) != address(0), "invalid RTokenTrader address");
101: require(address(val) != address(0), "invalid Furnace address");
109: require(address(val) != address(0), "invalid Broker address");
File: p1/AssetRegistry.sol
74: require(_erc20s.contains(address(asset.erc20())), "no ERC20 collision");
88: require(_erc20s.contains(address(asset.erc20())), "no asset to unregister");
89: require(assets[asset.erc20()] == asset, "asset not found");
103: require(_erc20s.contains(address(erc20)), "erc20 unregistered");
111: require(_erc20s.contains(address(erc20)), "erc20 unregistered");
112: require(assets[erc20].isCollateral(), "erc20 is not collateral");
File: p1/BackingManager.sol
73: require(assetRegistry.isRegistered(erc20), "erc20 unregistered");
85: require(ArrayLib.allUnique(erc20s), "duplicate tokens");
97: require(ArrayLib.sortedAndAllUnique(erc20s), "duplicate/unsorted tokens");
111: require(basketHandler.status() == CollateralStatus.SOUND, "basket not sound");
257: require(val <= MAX_TRADING_DELAY, "invalid tradingDelay");
264: require(val <= MAX_BACKING_BUFFER, "invalid backingBuffer");
File: p1/BasketHandler.sol
168: require(_msgSender() == address(assetRegistry), "asset registry only");
213: require(erc20s.length > 0, "cannot empty basket");
214: require(erc20s.length == targetAmts.length, "must be same length");
230: require(assetRegistry.toAsset(erc20s[i]).isCollateral(), "token is not collateral");
231: require(0 < targetAmts[i], "invalid target amount; must be nonzero");
232: require(targetAmts[i] <= MAX_TARGET_AMT, "invalid target amount; too large");
265: require(assetRegistry.toAsset(erc20s[i]).isCollateral(), "token is not collateral");
654: require(erc20s[i] != rsr, "RSR is not valid collateral");
655: require(erc20s[i] != IERC20(address(rToken)), "RToken is not valid collateral");
656: require(erc20s[i] != IERC20(address(stRSR)), "stRSR is not valid collateral");
657: require(erc20s[i] != zero, "address zero is not valid collateral");
660: require(ArrayLib.allUnique(erc20s), "contains duplicates");
File: p1/Broker.sol
57: require(address(gnosis_) != address(0), "invalid Gnosis address");
86: require(!disabled, "broker disabled");
125: require(trades[_msgSender()], "unrecognized trade contract");
File: p1/Deployer.sol
109: require(owner != address(0) && owner != address(this), "invalid owner");
File: p1/Distributor.sol
92: require(erc20 == rsr || erc20 == rToken, "RSR or RToken");
98: require(totalShares > 0, "nothing to distribute");
162: require(dest != address(0), "dest cannot be zero");
163: if (dest == FURNACE) require(share.rsrDist == 0, "Furnace must get 0% of RSR");
164: if (dest == ST_RSR) require(share.rTokenDist == 0, "StRSR must get 0% of RToken");
165: require(share.rsrDist <= 10000, "RSR distribution too high");
166: require(share.rTokenDist <= 10000, "RToken distribution too high");
172: require(destinations.length() <= MAX_DESTINATIONS_ALLOWED, "Too many destinations");
182: require(rTokenDist > 0 || rsrDist > 0, "no distribution defined");
File: p1/Furnace.sol
89: require(period_ > 0 && period_ <= MAX_PERIOD, "invalid period");
97: require(ratio_ <= MAX_RATIO, "invalid ratio");
File: p1/Main.sol
32: require(address(rsr_) != address(0), "invalid RSR address");
48: require(!pausedOrFrozen(), "paused or frozen");
File: p1/RToken.sol
156: require(bytes(name_).length > 0, "name empty");
157: require(bytes(symbol_).length > 0, "symbol empty");
158: require(bytes(mandate_).length > 0, "mandate empty");
191: require(amtRToken > 0, "Cannot issue zero");
217: require(status == CollateralStatus.SOUND, "basket unsound");
384: require(status == CollateralStatus.SOUND, "basket unsound");
410: require(queue.left <= endId && endId <= queue.right, "out of range");
440: require(amount > 0, "Cannot redeem zero");
448: require(basketHandler.status() != CollateralStatus.DISABLED, "collateral default");
513: if (allZero) revert("Empty redemption");
558: require(_msgSender() == address(backingManager), "not backing manager");
581: require(_msgSender() == address(backingManager), "not backing manager");
590: require(val > 0 && val <= MAX_ISSUANCE_RATE, "invalid issuanceRate");
603: require(val <= FIX_ONE, "invalid fraction");
623: require(index >= item.left && index < item.right, "out of range");
705: revert("Bad refundSpan");
741: require(queue.left <= endId && endId <= queue.right, "out of range");
747: require(rightItem.when <= FIX_ONE_256 * block.number, "issuance not ready");
813: require(uint192(low) >= 1e9 && uint192(high) <= 1e27, "BU rate out of range");
833: require(to != address(this), "RToken transfer to self");
File: p1/RevenueTrader.sol
29: require(address(tokenToBuy_) != address(0), "invalid token address");
72: require(buyPrice > 0 && buyPrice < FIX_MAX, "buy asset price unknown");
File: p1/StRSR.sol
168: require(bytes(name_).length > 0, "name empty");
169: require(bytes(symbol_).length > 0, "symbol empty");
213: require(rsrAmount > 0, "Cannot stake zero");
259: require(stakeAmount > 0, "Cannot withdraw zero");
260: require(stakes[era][account] >= stakeAmount, "Not enough balance");
305: require(basketHandler.fullyCollateralized(), "RToken uncollateralized");
306: require(basketHandler.status() == CollateralStatus.SOUND, "basket defaulted");
312: require(endId <= queue.length, "index out-of-bounds");
313: require(queue[endId - 1].availableAt <= block.timestamp, "withdrawal unavailable");
375: require(_msgSender() == address(backingManager), "not backing manager");
376: require(rsrAmount > 0, "Amount cannot be zero");
380: require(rsrAmount <= rsrBalance, "Cannot seize more RSR than we hold");
660: require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
675: require(from != address(0), "ERC20: transfer from the zero address");
676: require(to != address(0), "ERC20: transfer to the zero address");
680: require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
695: require(account != address(0), "ERC20: mint to the zero address");
711: require(account != address(0), "ERC20: burn from the zero address");
717: require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
732: require(owner != address(0), "ERC20: approve from the zero address");
733: require(spender != address(0), "ERC20: approve to the zero address");
746: require(currentAllowance >= amount, "ERC20: insufficient allowance");
760: require(to != address(this), "StRSR transfer to self");
775: require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
813: require(val > 0 && val <= MAX_UNSTAKING_DELAY, "invalid unstakingDelay");
816: require(rewardPeriod * 2 <= unstakingDelay, "unstakingDelay/rewardPeriod incompatible");
821: require(val > 0 && val <= MAX_REWARD_PERIOD, "invalid rewardPeriod");
824: require(rewardPeriod * 2 <= unstakingDelay, "unstakingDelay/rewardPeriod incompatible");
829: require(val <= MAX_REWARD_RATIO, "invalid rewardRatio");
File: p1/StRSRVotes.sol
77: require(blockNumber < block.number, "ERC20Votes: block not yet mined");
83: require(blockNumber < block.number, "ERC20Votes: block not yet mined");
89: require(blockNumber < block.number, "ERC20Votes: block not yet mined");
126: require(block.timestamp <= expiry, "ERC20Votes: signature expired");
133: require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce");
File: p1/mixins/Component.sol
34: require(address(main_) != address(0), "main is zero address");
42: require(!main.pausedOrFrozen(), "paused or frozen");
47: require(!main.frozen(), "frozen");
52: require(main.hasRole(OWNER, _msgSender()), "governance only");
File: p1/mixins/RewardableLib.sol
96: require(reg.isRegistered(erc20), "erc20 unregistered");
File: p1/mixins/Trading.sol
69: require(trade.canSettle(), "cannot settle yet");
129: require(val < MAX_TRADE_SLIPPAGE, "invalid maxTradeSlippage");
136: require(val <= MIN_TRADE_VOLUME, "invalid minTradeVolume");
File: plugins/aave/ERC20.sol
242: require(sender != address(0), "ERC20: transfer from the zero address");
243: require(recipient != address(0), "ERC20: transfer to the zero address");
262: require(account != address(0), "ERC20: mint to the zero address");
283: require(account != address(0), "ERC20: burn from the zero address");
310: require(owner != address(0), "ERC20: approve from the zero address");
311: require(spender != address(0), "ERC20: approve to the zero address");
File: plugins/aave/ReentrancyGuard.sol
51: require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
File: plugins/assets/Asset.sol
48: require(priceTimeout_ > 0, "price timeout zero");
49: require(address(chainlinkFeed_) != address(0), "missing chainlink feed");
50: require(oracleError_ > 0 && oracleError_ < FIX_ONE, "oracle error out of range");
51: require(address(erc20_) != address(0), "missing erc20");
52: require(maxTradeVolume_ > 0, "invalid max trade volume");
53: require(oracleTimeout_ > 0, "oracleTimeout zero");
File: plugins/assets/CTokenFiatCollateral.sol
26: require(address(comptroller_) != address(0), "comptroller missing");
File: plugins/assets/CTokenSelfReferentialCollateral.sol
29: require(referenceERC20Decimals_ > 0, "referenceERC20Decimals missing");
30: require(address(comptroller_) != address(0), "comptroller missing");
File: plugins/assets/EURFiatCollateral.sol
24: require(address(uoaPerTargetFeed_) != address(0), "missing uoaPerTarget feed");
File: plugins/assets/FiatCollateral.sol
73: require(config.targetName != bytes32(0), "targetName missing");
75: require(config.delayUntilDefault > 0, "delayUntilDefault zero");
File: plugins/assets/NonFiatCollateral.sol
24: require(address(uoaPerTargetFeed_) != address(0), "missing uoaPerTarget feed");
File: plugins/assets/RTokenAsset.sol
28: require(address(erc20_) != address(0), "missing erc20");
29: require(maxTradeVolume_ > 0, "invalid max trade volume");
File: plugins/assets/SelfReferentialCollateral.sol
19: require(config.defaultThreshold == 0, "default threshold not supported");
File: plugins/governance/Governance.sol
102: require(startedInSameEra(proposalId), "new era");
112: require(!startedInSameEra(proposalId), "same era");
123: require(startedInSameEra(proposalId), "new era");
File: plugins/mocks/BadERC20.sol
41: if (censored[owner] || censored[to]) revert("censored");
54: if (censored[from] || censored[to]) revert("censored");
File: plugins/mocks/EasyAuction.sol
131: require(newFeeNumerator <= 15, "Fee is not allowed to be set higher than 1.5%");
164: require(_auctionedSellAmount > 0, "cannot auction zero tokens");
165: require(_minBuyAmount > 0, "tokens cannot be auctioned for free");
174: require(auctionEndDate > block.timestamp, "auction end date must be in the future");
289: require(_minBuyAmounts[i] > 0, "_minBuyAmounts must be greater than 0");
292: require(_sellAmounts[i] > minimumBiddingAmountPerOrder, "order too small");
326: require(userIdOfIter == userId, "Only the user can cancel his orders");
350: require(iterOrder != IterableOrderedOrderSet.QUEUE_END, "reached end of order list");
516: require(sellOrders[auctionId].remove(orders[i]), "order is no longer claimable");
526: require(userIdOrder == userId, "only allowed to claim for same user");
607: require(registeredUsers.insert(numUsers, user), "User already registered");
File: plugins/mocks/GnosisMock.sol
69: require(auctionedSellAmount > 0, "sell amount is zero");
91: require(bid.sellAmount <= auctions[auctionId].sellAmount, "invalid bid sell");
92: require(bid.buyAmount > 0, "zero volume bid");
100: require(auction.endTime <= block.timestamp, "too early to close auction");
101: require(auction.status == MauctionStatus.OPEN, "auction already closed");
File: plugins/mocks/GnosisMockReentrant.sol
33: require(auctionedSellAmount > 0, "sell amount is zero");
61: require(auction.endTime <= block.timestamp, "too early to close auction");
62: require(auction.status == MauctionStatus.OPEN, "auction already closed");
File: plugins/mocks/InvalidATokenFiatCollateralMock.sol
11: revert("claimRewards() error");
File: plugins/mocks/InvalidBrokerMock.sol
39: require(!disabled, "broker disabled");
43: revert("Failure opening trade");
File: plugins/mocks/InvalidFiatCollateral.sol
17: revert("errormsg"); // Revert with no reason
File: plugins/mocks/RTokenCollateral.sol
43: require(targetName_ != bytes32(0), "targetName missing");
File: plugins/mocks/upgrades/MainV2.sol
10: require(!pausedOrFrozen(), "paused or frozen");
File: plugins/mocks/vendor/EasyAuction.sol
205: require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
258: require(denominator != uint96(0), "Inserting zero is not supported");
362: require(userIdLeft != userIdRight, "user is not allowed to place same order twice");
370: require(!isEmpty(self), "Trying to get first from empty set");
375: require(value != QUEUE_END, "Trying to get next of last element");
377: require(nextElement != bytes32(0), "Trying to get next of non-existent element");
460: require(c >= a, "SafeMath: addition overflow");
519: require(c / a == b, "SafeMath: multiplication overflow");
623: require(hasId(self, id), "Must have ID to get Address");
628: require(hasAddress(self, addr), "Must have Address to get ID");
637: require(addr != address(0), "Cannot insert zero address");
638: require(id != uint64(-1), "Cannot insert max uint64");
657: require(value < 2**96, "SafeCast: value doesn't fit in 96 bits");
662: require(value < 2**64, "SafeCast: value doesn't fit in 64 bits");
718: require(address(this).balance >= amount, "Address: insufficient balance");
722: require(success, "Address: unable to send value, recipient may have reverted");
793: require(address(this).balance >= value, "Address: insufficient balance for call");
794: require(isContract(target), "Address: call to non-contract");
826: require(isContract(target), "Address: static call to non-contract");
915: require(_owner == _msgSender(), "Ownable: caller is not the owner");
936: require(newOwner != address(0), "Ownable: new owner is the zero address");
File: plugins/trading/GnosisTrade.sol
60: require(status == begin, "Invalid trade state");
88: require(req.sellAmount <= type(uint96).max, "sellAmount too large");
89: require(req.minBuyAmount <= type(uint96).max, "minBuyAmount too large");
95: require(initBal <= type(uint96).max, "initBal too large");
96: require(initBal >= req.sellAmount, "unfunded trade");
174: require(msg.sender == origin, "only origin can settle");
216: require(status == TradeStatus.CLOSED, "only after trade is closed");
File: vendor/ERC20PermitUpgradeable.sol
81: require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
Instances (66):
File: libraries/Array.sol
12: for (uint256 j = 0; j < i; ++j) {
File: libraries/Fixed.sol
50: uint192 constant FIX_ZERO = 0; // The uint192 representation of zero.
53: uint192 constant FIX_MIN = 0; // The smallest uint192.
File: libraries/String.sol
14: for (uint256 i = 0; i < bStr.length; i++) {
File: p1/AssetRegistry.sol
38: for (uint256 i = 0; i < length; ++i) {
49: for (uint256 i = 0; i < length; ++i) {
127: for (uint256 i = 0; i < length; ++i) {
138: for (uint256 i = 0; i < length; ++i) {
File: p1/BackingManager.sol
221: for (uint256 i = 0; i < length; ++i) {
238: for (uint256 i = 0; i < length; ++i) {
File: p1/BasketHandler.sol
70: for (uint256 i = 0; i < length; ++i) self.refAmts[self.erc20s[i]] = FIX_ZERO;
78: for (uint256 i = 0; i < length; ++i) {
218: for (uint256 i = 0; i < config.erc20s.length; ++i) {
227: for (uint256 i = 0; i < erc20s.length; ++i) {
262: for (uint256 i = 0; i < erc20s.length; ++i) {
286: for (uint256 i = 0; i < size; ++i) {
337: for (uint256 i = 0; i < len; ++i) {
397: for (uint256 i = 0; i < len; ++i) {
416: for (uint256 i = 0; i < length; ++i) {
437: for (uint256 i = 0; i < length; ++i) {
530: for (uint256 i = 0; i < basketLength; ++i) {
548: for (uint256 i = 0; i < basketLength; ++i) {
586: for (uint256 i = 0; i < targetsLength; ++i) {
592: uint256 size = 0; // backup basket size
597: for (uint256 j = 0; j < backupLength && size < backup.max; ++j) {
606: uint256 assigned = 0;
611: for (uint256 j = 0; j < backupLength && assigned < size; ++j) {
643: for (uint256 i = 0; i < basketLength; ++i) {
653: for (uint256 i = 0; i < erc20s.length; i++) {
707: for (uint256 i = 0; i < erc20s.length; ++i) {
725: for (uint256 i = 0; i < erc20s.length; ++i) {
File: p1/Distributor.sol
108: for (uint256 i = 0; i < destinations.length(); ++i) {
133: for (uint256 i = 0; i < numTransfers; i++) {
143: for (uint256 i = 0; i < length; ++i) {
File: p1/RToken.sol
270: for (uint256 i = 0; i < erc20s.length; ++i) {
303: for (uint256 i = 0; i < basketSize; ++i) {
329: for (uint256 i = 0; i < basketSize; ++i) {
334: for (uint256 i = 0; i < basketSize; ++i) {
478: for (uint256 i = 0; i < erc20length; ++i) {
501: for (uint256 i = 0; i < erc20length; ++i) {
674: for (uint256 i = 0; i < tokensLen; ++i) {
683: for (uint256 i = 0; i < tokensLen; ++i) {
711: for (uint256 i = 0; i < queue.tokens.length; ++i) {
757: for (uint256 i = 0; i < tokensLen; ++i) {
767: for (uint256 i = 0; i < tokensLen; ++i) {
793: for (uint256 i = 0; i < tokensLen; ++i) {
File: p1/StRSRVotes.sol
102: uint256 low = 0;
File: p1/mixins/RecollateralizationLib.sol
242: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
329: for (uint256 i = 0; i < reg.erc20s.length; ++i) {
437: for (uint256 i = 0; i < len; ++i) {
File: p1/mixins/RewardableLib.sol
27: for (uint256 i = 0; i < registry.assets.length; ++i) {
67: for (uint256 i = 0; i < erc20sLen; ++i) {
73: for (uint256 i = 0; i < erc20sLen; ++i) {
File: plugins/mocks/ChainlinkMock.sol
17: uint256 public constant override version = 0;
File: plugins/mocks/EasyAuction.sol
123: uint256 public feeNumerator = 0;
277: for (uint256 i = 0; i < _minBuyAmounts.length; i++) {
285: uint256 sumOfSellAmounts = 0;
288: for (uint256 i = 0; i < _minBuyAmounts.length; i++) {
315: uint256 claimableAmount = 0;
316: for (uint256 i = 0; i < _sellOrders.length; i++) {
344: for (uint256 i = 0; i < iterationSteps; i++) {
513: for (uint256 i = 0; i < orders.length; i++) {
524: for (uint256 i = 0; i < orders.length; i++) {
File: plugins/mocks/GnosisMock.sol
50: uint256 public constant feeNumerator = 0; // Does not support a fee
File: plugins/mocks/InvalidChainlinkMock.sol
51: uint256 i = 0;
File: plugins/mocks/InvalidFiatCollateral.sol
32: uint256 i = 0;
Instances (36):
File: p1/BasketHandler.sol
231: require(0 < targetAmts[i], "invalid target amount; must be nonzero");
657: require(erc20s[i] != zero, "address zero is not valid collateral");
File: p1/StRSR.sol
380: require(rsrAmount <= rsrBalance, "Cannot seize more RSR than we hold");
660: require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
675: require(from != address(0), "ERC20: transfer from the zero address");
676: require(to != address(0), "ERC20: transfer to the zero address");
680: require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
711: require(account != address(0), "ERC20: burn from the zero address");
717: require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
732: require(owner != address(0), "ERC20: approve from the zero address");
733: require(spender != address(0), "ERC20: approve to the zero address");
816: require(rewardPeriod * 2 <= unstakingDelay, "unstakingDelay/rewardPeriod incompatible");
824: require(rewardPeriod * 2 <= unstakingDelay, "unstakingDelay/rewardPeriod incompatible");
File: plugins/aave/ERC20.sol
242: require(sender != address(0), "ERC20: transfer from the zero address");
243: require(recipient != address(0), "ERC20: transfer to the zero address");
283: require(account != address(0), "ERC20: burn from the zero address");
310: require(owner != address(0), "ERC20: approve from the zero address");
311: require(spender != address(0), "ERC20: approve to the zero address");
File: plugins/mocks/EasyAuction.sol
131: require(newFeeNumerator <= 15, "Fee is not allowed to be set higher than 1.5%");
165: require(_minBuyAmount > 0, "tokens cannot be auctioned for free");
174: require(auctionEndDate > block.timestamp, "auction end date must be in the future");
289: require(_minBuyAmounts[i] > 0, "_minBuyAmounts must be greater than 0");
326: require(userIdOfIter == userId, "Only the user can cancel his orders");
526: require(userIdOrder == userId, "only allowed to claim for same user");
File: plugins/mocks/vendor/EasyAuction.sol
205: require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
362: require(userIdLeft != userIdRight, "user is not allowed to place same order twice");
370: require(!isEmpty(self), "Trying to get first from empty set");
375: require(value != QUEUE_END, "Trying to get next of last element");
377: require(nextElement != bytes32(0), "Trying to get next of non-existent element");
519: require(c / a == b, "SafeMath: multiplication overflow");
657: require(value < 2**96, "SafeCast: value doesn't fit in 96 bits");
662: require(value < 2**64, "SafeCast: value doesn't fit in 64 bits");
722: require(success, "Address: unable to send value, recipient may have reverted");
793: require(address(this).balance >= value, "Address: insufficient balance for call");
826: require(isContract(target), "Address: static call to non-contract");
936: require(newOwner != address(0), "Ownable: new owner is the zero address");
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 (16):
File: mixins/Auth.sol
65: function __Auth_init(uint48 shortFreeze_, uint48 longFreeze_) internal onlyInitializing {
120: function freezeShort() external onlyRole(SHORT_FREEZER) {
135: function freezeLong() external onlyRole(LONG_FREEZER) {
148: function freezeForever() external onlyRole(OWNER) {
157: function unfreeze() external onlyRole(OWNER) {
165: function pause() external onlyRole(PAUSER) {
172: function unpause() external onlyRole(PAUSER) {
180: function setShortFreeze(uint48 shortFreeze_) public onlyRole(OWNER) {
187: function setLongFreeze(uint48 longFreeze_) public onlyRole(OWNER) {
File: mixins/ComponentRegistry.sol
19: function __ComponentRegistry_init(Components memory components_) internal onlyInitializing {
File: p1/Main.sol
64: function _authorizeUpgrade(address newImplementation) internal override onlyRole(OWNER) {}
File: p1/mixins/Component.sol
33: function __Component_init(IMain main_) internal onlyInitializing {
File: plugins/mocks/vendor/EasyAuction.sol
926: function renounceOwnership() public virtual onlyOwner {
935: function transferOwnership(address newOwner) public virtual onlyOwner {
File: vendor/ERC20PermitUpgradeable.sol
61: function __ERC20Permit_init(string memory name) internal onlyInitializing {
67: function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {}
Saves 5 gas per loop
Instances (21):
File: libraries/Fixed.sol
165: result++;
169: result++;
File: libraries/String.sol
14: for (uint256 i = 0; i < bStr.length; i++) {
File: p1/BasketHandler.sol
598: if (goodCollateral(_targetNames.at(i), backup.erc20s[j])) size++;
621: assigned++;
653: for (uint256 i = 0; i < erc20s.length; i++) {
File: p1/Distributor.sol
128: numTransfers++;
133: for (uint256 i = 0; i < numTransfers; i++) {
File: p1/RToken.sol
316: queue.right++;
File: p1/StRSR.sol
578: era++;
590: draftEra++;
File: p1/mixins/Trading.sol
121: tradesOpen++;
File: plugins/mocks/ChainlinkMock.sol
39: latestRound++;
File: plugins/mocks/EasyAuction.sol
277: for (uint256 i = 0; i < _minBuyAmounts.length; i++) {
288: for (uint256 i = 0; i < _minBuyAmounts.length; i++) {
316: for (uint256 i = 0; i < _sellOrders.length; i++) {
344: for (uint256 i = 0; i < iterationSteps; i++) {
513: for (uint256 i = 0; i < orders.length; i++) {
524: for (uint256 i = 0; i < orders.length; i++) {
File: plugins/mocks/InvalidChainlinkMock.sol
55: i++;
File: plugins/mocks/InvalidFiatCollateral.sol
36: i++;
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 (38):
File: mixins/Auth.sol
27: bytes32 public constant OWNER_ROLE = OWNER;
28: bytes32 public constant SHORT_FREEZER_ROLE = SHORT_FREEZER;
29: bytes32 public constant LONG_FREEZER_ROLE = LONG_FREEZER;
30: bytes32 public constant PAUSER_ROLE = PAUSER;
File: p1/BackingManager.sol
33: uint48 public constant MAX_TRADING_DELAY = 31536000; // {s} 1 year
34: uint192 public constant MAX_BACKING_BUFFER = FIX_ONE; // {1} 100%
File: p1/BasketHandler.sol
117: uint192 public constant MAX_TARGET_AMT = 1e3 * FIX_ONE; // {target/BU} max basket weight
File: p1/Broker.sol
24: uint48 public constant MAX_AUCTION_LENGTH = 604800; // {s} max valid duration - 1 week
File: p1/Deployer.sol
31: string public constant ENS = "reserveprotocol.eth";
File: p1/Distributor.sol
31: address public constant FURNACE = address(1);
32: address public constant ST_RSR = address(2);
34: uint8 public constant MAX_DESTINATIONS_ALLOWED = 100;
File: p1/Furnace.sol
15: uint192 public constant MAX_RATIO = FIX_ONE; // {1} 100%
16: uint48 public constant MAX_PERIOD = 31536000; // {s} 1 year
File: p1/StRSR.sol
37: uint48 public constant MAX_UNSTAKING_DELAY = 31536000; // {s} 1 year
38: uint48 public constant MAX_REWARD_PERIOD = 31536000; // {s} 1 year
39: uint192 public constant MAX_REWARD_RATIO = FIX_ONE; // {1} 100%
45: uint8 public constant decimals = 18;
File: p1/mixins/Trading.sol
20: uint192 public constant MIN_TRADE_VOLUME = 1e29; // {UoA}
21: uint192 public constant MAX_TRADE_SLIPPAGE = 1e18; // {%}
File: plugins/aave/StaticATokenErrors.sol
5: string public constant INVALID_OWNER = "1";
6: string public constant INVALID_EXPIRATION = "2";
7: string public constant INVALID_SIGNATURE = "3";
8: string public constant INVALID_DEPOSITOR = "4";
9: string public constant INVALID_RECIPIENT = "5";
10: string public constant INVALID_CLAIMER = "6";
11: string public constant ONLY_ONE_AMOUNT_FORMAT_ALLOWED = "7";
File: plugins/aave/StaticATokenLM.sol
40: bytes public constant EIP712_REVISION = bytes("1");
45: bytes32 public constant PERMIT_TYPEHASH =
49: bytes32 public constant METADEPOSIT_TYPEHASH =
53: bytes32 public constant METAWITHDRAWAL_TYPEHASH =
58: uint256 public constant STATIC_ATOKEN_LM_REVISION = 0x1;
File: plugins/mocks/ChainlinkMock.sol
17: uint256 public constant override version = 0;
File: plugins/mocks/EasyAuction.sol
124: uint256 public constant FEE_DENOMINATOR = 1000;
File: plugins/mocks/GnosisMock.sol
50: uint256 public constant feeNumerator = 0; // Does not support a fee
File: plugins/trading/GnosisTrade.sol
27: uint256 public constant FEE_DENOMINATOR = 1000;
31: uint96 public constant MAX_ORDERS = 1e5;
34: uint192 public constant DEFAULT_MIN_BID = FIX_ONE / 100; // {tok}
Instances (5):
File: libraries/Fixed.sol
164: if (numerator % divisor > (divisor - 1) / 2) {
310: uint64 constant FIX_HALF = uint64(FIX_SCALE) / 2;
323: if (y & 1 == 1) result = (result * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
326: x = (x * x + FIX_SCALE_SQ / 2) / FIX_SCALE_SQ;
539: if (mm > ((z - 1) / 2)) result += 1; // z should be z-1
Instances (96):
File: libraries/Fixed.sol
101: if (shiftLeft <= -96) return (rounding == CEIL ? 1 : 0); // 0 < uint.max / 10**77 < 0.5
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
168: if (numerator % divisor > 0) {
537: if (mm > 0) result += 1;
File: mixins/Auth.sol
45: 0 <= longFreeze[a] <= LONG_FREEZE_CHARGES for all addrs a
181: require(shortFreeze_ > 0 && shortFreeze_ <= MAX_SHORT_FREEZE, "short freeze out of range");
188: require(longFreeze_ > 0 && longFreeze_ <= MAX_LONG_FREEZE, "long freeze out of range");
File: p1/AssetRegistry.sol
78: if (quantity > 0) basketHandler.disableBasket();
96: if (quantity > 0) basketHandler.disableBasket();
File: p1/BackingManager.sol
109: if (tradesOpen > 0) return;
173: if (rsr.balanceOf(address(this)) > 0) {
200: uint192 rTok = (needed > 0) ? extraBUs.mulDiv(totalSupply, needed) : extraBUs;
240: if (toRToken[i] > 0) erc20.safeTransfer(address(rTokenTrader), toRToken[i]);
241: if (toRSR[i] > 0) erc20.safeTransfer(address(rsrTrader), toRSR[i]);
File: p1/BasketHandler.sol
213: require(erc20s.length > 0, "cannot empty basket");
231: require(0 < targetAmts[i], "invalid target amount; must be nonzero");
301: if (refPerTok > 0) {
486: If unsoundPrimeWt(tgt) > 0 and len(backups(tgt)) == 0 for some tgt, then disabled' == true.
523: while (_targetNames.length() > 0) _targetNames.remove(_targetNames.at(0));
679: coll.refPerTok() > 0 &&
680: coll.targetPerRef() > 0;
File: p1/Broker.sol
135: newAuctionLength > 0 && newAuctionLength <= MAX_AUCTION_LENGTH,
File: p1/Distributor.sol
98: require(totalShares > 0, "nothing to distribute");
182: require(rTokenDist > 0 || rsrDist > 0, "no distribution defined");
182: require(rTokenDist > 0 || rsrDist > 0, "no distribution defined");
File: p1/Furnace.sol
83: if (amount > 0) rToken.melt(amount);
89: require(period_ > 0 && period_ <= MAX_PERIOD, "invalid period");
File: p1/RToken.sol
156: require(bytes(name_).length > 0, "name empty");
157: require(bytes(symbol_).length > 0, "symbol empty");
158: require(bytes(mandate_).length > 0, "mandate empty");
191: require(amtRToken > 0, "Cannot issue zero");
202: if (queue.basketNonce > 0 && queue.basketNonce != basketNonce) {
234: totalSupply() > 0 ? mulDiv256(basketsNeeded, amtRToken, totalSupply()) : amtRToken
295: if (queue.right > 0) {
440: require(amount > 0, "Cannot redeem zero");
483: uint256 prorata = (prorate > 0)
590: require(val > 0 && val <= MAX_ISSUANCE_RATE, "invalid issuanceRate");
File: p1/RevenueTrader.sol
72: require(buyPrice > 0 && buyPrice < FIX_MAX, "buy asset price unknown");
File: p1/StRSR.sol
168: require(bytes(name_).length > 0, "name empty");
169: require(bytes(symbol_).length > 0, "symbol empty");
213: require(rsrAmount > 0, "Cannot stake zero");
259: require(stakeAmount > 0, "Cannot withdraw zero");
315: uint192 oldDrafts = firstId > 0 ? queue[firstId - 1].drafts : 0;
376: require(rsrAmount > 0, "Amount cannot be zero");
391: if (stakeRSR > 0) {
406: if (draftRSR > 0) {
504: if (totalStakes > 0) {
559: uint192 oldDrafts = index > 0 ? queue[index - 1].drafts : 0;
560: uint64 lastAvailableAt = index > 0 ? queue[index - 1].availableAt : 0;
813: require(val > 0 && val <= MAX_UNSTAKING_DELAY, "invalid unstakingDelay");
821: require(val > 0 && val <= MAX_REWARD_PERIOD, "invalid rewardPeriod");
File: p1/StRSRVotes.sol
171: if (src != dst && amount > 0) {
202: if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {
File: p1/mixins/RecollateralizationLib.sol
411: high > 0 &&
File: p1/mixins/RewardableLib.sol
74: if (deltas[i] > 0) {
98: if (amt > 0) {
File: p1/mixins/TradeLib.sol
44: assert(trade.buyPrice > 0 && trade.buyPrice < FIX_MAX && trade.sellPrice < FIX_MAX);
109: trade.sellPrice > 0 &&
111: trade.buyPrice > 0 &&
183: return size > 0 ? size : 1;
192: return size > 0 ? size : 1;
File: plugins/aave/ReentrancyGuard.sol
3: pragma solidity >=0.6.0 <0.8.0;
3: pragma solidity >=0.6.0 <0.8.0;
File: plugins/aave/StaticATokenLM.sol
330: if (staticAmount > 0) {
422: if (supply > 0 && rewardsAccrued > 0) {
422: if (supply > 0 && rewardsAccrued > 0) {
428: if (rewardsAccrued > 0) {
461: if (reward > 0) {
512: if (balance > 0) {
File: plugins/assets/Asset.sol
48: require(priceTimeout_ > 0, "price timeout zero");
50: require(oracleError_ > 0 && oracleError_ < FIX_ONE, "oracle error out of range");
52: require(maxTradeVolume_ > 0, "invalid max trade volume");
53: require(oracleTimeout_ > 0, "oracleTimeout zero");
File: plugins/assets/CTokenSelfReferentialCollateral.sol
29: require(referenceERC20Decimals_ > 0, "referenceERC20Decimals missing");
File: plugins/assets/FiatCollateral.sol
74: if (config.defaultThreshold > 0) {
75: require(config.delayUntilDefault > 0, "delayUntilDefault zero");
File: plugins/assets/RTokenAsset.sol
29: require(maxTradeVolume_ > 0, "invalid max trade volume");
File: plugins/mocks/ATokenMock.sol
81: if (address(aaveToken) != address(0) && aaveBalances[msg.sender] > 0) {
File: plugins/mocks/AaveLendingPoolMock.sol
36: return _normalizedIncome[asset] > 0 ? _normalizedIncome[asset] : 1e27;
File: plugins/mocks/EasyAuction.sol
164: require(_auctionedSellAmount > 0, "cannot auction zero tokens");
165: require(_minBuyAmount > 0, "tokens cannot be auctioned for free");
167: minimumBiddingAmountPerOrder > 0,
289: require(_minBuyAmounts[i] > 0, "_minBuyAmounts must be greater than 0");
427: currentBidSum > 0 &&
597: if (auctioningTokenAmount > 0) {
600: if (biddingTokenAmount > 0) {
File: plugins/mocks/GnosisMock.sol
69: require(auctionedSellAmount > 0, "sell amount is zero");
92: require(bid.buyAmount > 0, "zero volume bid");
File: plugins/mocks/GnosisMockReentrant.sol
33: require(auctionedSellAmount > 0, "sell amount is zero");
File: plugins/mocks/WETH.sol
16: pragma solidity >=0.4.22 <0.6;
File: plugins/mocks/vendor/EasyAuction.sol
202: if (returndata.length > 0) {
557: require(b > 0, errorMessage);
698: return size > 0;
842: if (returndata.length > 0) {
File: plugins/trading/GnosisTrade.sol
191: if (sellBal > 0) IERC20Upgradeable(address(sell)).safeTransfer(origin, sellBal);
192: if (boughtAmt > 0) IERC20Upgradeable(address(buy)).safeTransfer(origin, boughtAmt);
Issue | Instances | |
---|---|---|
NC-1 | Return values of approve() not checked |
12 |
NC-2 | Constants should be defined rather than using magic numbers | 3 |
Not all IERC20 implementations revert()
when there's a failure in approve()
. The function signature has a boolean return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually approving anything
Instances (12):
File: p1/StRSR.sol
633: _approve(_msgSender(), spender, amount);
653: _approve(owner, spender, _allowances[era][owner][spender] + addedValue);
662: _approve(owner, spender, currentAllowance - subtractedValue);
748: _approve(owner, spender, currentAllowance - amount);
783: _approve(owner, spender, value);
File: plugins/aave/ERC20.sol
143: _approve(_msgSender(), spender, amount);
165: _approve(
189: _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
212: _approve(
File: plugins/aave/StaticATokenLM.sol
157: _approve(owner, spender, value);
File: plugins/mocks/ERC20Mock.sol
23: _approve(owner, spender, amount);
File: vendor/ERC20PermitUpgradeable.sol
93: _approve(owner, spender, value);
Instances (3):
File: libraries/Fixed.sol
102: if (40 <= shiftLeft) revert UIntOutOfBounds(); // 10**56 < FIX_MAX < 10**57
213: if (58 <= decimals) revert UIntOutOfBounds(); // 58, because x * 1e58 > 2 ** 192 if x != 0
390: if (96 <= decimals) revert UIntOutOfBounds();
Issue | Instances | |
---|---|---|
L-1 | Do not use deprecated library functions | 10 |
L-2 | Unsafe ERC20 operation(s) | 1 |
L-3 | Unspecific compiler version pragma | 2 |
Instances (10):
File: p1/BackingManager.sol
75: IERC20Upgradeable(address(erc20)).safeApprove(address(main.rToken()), 0);
76: IERC20Upgradeable(address(erc20)).safeApprove(address(main.rToken()), type(uint256).max);
File: p1/RevenueTrader.sol
61: IERC20Upgradeable(address(erc20)).safeApprove(address(distributor), 0);
62: IERC20Upgradeable(address(erc20)).safeApprove(address(distributor), bal);
File: p1/mixins/Trading.sol
116: IERC20Upgradeable(address(sell)).safeApprove(address(broker), 0);
117: IERC20Upgradeable(address(sell)).safeApprove(address(broker), req.sellAmount);
File: plugins/aave/StaticATokenLM.sol
101: ASSET.safeApprove(address(pool), type(uint256).max);
File: plugins/mocks/vendor/EasyAuction.sol
144: function safeApprove(
File: plugins/trading/GnosisTrade.sol
136: IERC20Upgradeable(address(sell)).safeApprove(address(gnosis), 0);
137: IERC20Upgradeable(address(sell)).safeApprove(address(gnosis), initBal);
Instances (1):
File: plugins/mocks/WETH.sol
45: msg.sender.transfer(wad);
Instances (2):
File: plugins/aave/ReentrancyGuard.sol
3: pragma solidity >=0.6.0 <0.8.0;
File: plugins/mocks/WETH.sol
16: pragma solidity >=0.4.22 <0.6;
Issue | Instances | |
---|---|---|
M-1 | Centralization Risk for trusted owners | 21 |
Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds.
Instances (21):
File: interfaces/IMain.sol
48: interface IAuth is IAccessControlUpgradeable {
149: interface IMain is IVersioned, IAuth, IComponentRegistry {
File: mixins/Auth.sol
16: abstract contract Auth is AccessControlUpgradeable, IAuth {
16: abstract contract Auth is AccessControlUpgradeable, IAuth {
92: onlyRole(getRoleAdmin(role))
120: function freezeShort() external onlyRole(SHORT_FREEZER) {
135: function freezeLong() external onlyRole(LONG_FREEZER) {
148: function freezeForever() external onlyRole(OWNER) {
157: function unfreeze() external onlyRole(OWNER) {
165: function pause() external onlyRole(PAUSER) {
172: function unpause() external onlyRole(PAUSER) {
180: function setShortFreeze(uint48 shortFreeze_) public onlyRole(OWNER) {
187: function setLongFreeze(uint48 longFreeze_) public onlyRole(OWNER) {
File: mixins/ComponentRegistry.sol
13: abstract contract ComponentRegistry is Initializable, Auth, IComponentRegistry {
File: p1/Main.sol
18: contract MainP1 is Versioned, Initializable, Auth, ComponentRegistry, UUPSUpgradeable, IMain {
64: function _authorizeUpgrade(address newImplementation) internal override onlyRole(OWNER) {}
File: plugins/mocks/EasyAuction.sol
8: contract EasyAuction is Ownable {
121: constructor() public Ownable() {}
File: plugins/mocks/vendor/EasyAuction.sol
890: abstract contract Ownable is Context {
926: function renounceOwnership() public virtual onlyOwner {
935: function transferOwnership(address newOwner) public virtual onlyOwner {