Platform: Code4rena
Start Date: 10/11/2023
Pot Size: $28,000 USDC
Total HM: 5
Participants: 185
Period: 5 days
Judge: 0xDjango
Id: 305
League: ETH
Rank: 141/185
Findings: 1
Award: $2.76
π Selected for report: 0
π Solo Findings: 0
π Selected for report: m_Rassska
Also found by: 0x1337, 0xAadi, 0xHelium, 0xLeveler, 0xblackskull, 0xbrett8571, 0xepley, 0xffchain, 0xluckhu, 0xmystery, 0xrugpull_detector, 0xvj, ABAIKUNANBAEV, Aamir, AerialRaider, Amithuddar, Bauchibred, Bauer, CatsSecurity, Cryptor, Daniel526, Draiakoo, Eigenvectors, ElCid, GREY-HAWK-REACH, Inspecktor, Juntao, King_, LinKenji, Madalad, MaslarovK, Matin, MatricksDeCoder, McToady, Noro, PENGUN, Pechenite, Phantasmagoria, RaoulSchaffranek, SBSecurity, SandNallani, Shaheen, Soul22, Stormreckson, T1MOH, Tadev, TeamSS, TheSchnilch, Topmark, Tumelo_Crypto, Udsen, Yanchuan, ZanyBonzy, _thanos1, adeolu, adriro, alexfilippov314, almurhasan, amaechieth, anarcheuz, ayden, baice, bareli, boredpukar, bronze_pickaxe, btk, cartlex_, catellatech, chaduke, cheatc0d3, circlelooper, codynhat, crack-the-kelp, critical-or-high, debo, deepkin, desaperh, dipp, eeshenggoh, evmboi32, ge6a, gesha17, glcanvas, gumgumzum, hals, hihen, hunter_w3b, jasonxiale, joaovwfreire, ke1caM, leegh, lsaudit, marchev, merlinboii, niser93, osmanozdemir1, paritomarrr, passion, pep7siup, phoenixV110, pipidu83, poneta, ro1sharkm, rouhsamad, rvierdiiev, sakshamguruji, seerether, shealtielanz, soliditytaker, spark, squeaky_cactus, stackachu, supersizer0x, tallo, taner2344, turvy_fuzz, twcctop, ubl4nk, wisdomn_, xAriextz, zach, zhaojie, zhaojohnson, ziyou-
2.7592 USDC - $2.76
Audit report for REPO_GITHUB generated by Dowsers<br>
Total 32 instances over 3 issues<br>
ID | Issue | Instances |
---|---|---|
SWC-107 | Reentrancy | 13 |
SWC-120 | Weak sources of randomness from chain attributes | 18 |
SWC-127 | Arbitrary jump with function type variable | 1 |
Total 214 instances over 4 issues<br>
ID | Issue | Instances |
---|---|---|
SWC-XX1 | Insufficient coverage | 80 |
SWC-111 | Use of deprecated functions, aliases and keywords | 48 |
SWC-XX2 | Incorrect comparison implementation | 80 |
SWC-110 | require() should be used instead of assert() | 6 |
Description:<br> Reduce the attack surface for malicious contracts trying to hijack control flow after an external call. <br> https://swcregistry.io/docs/SWC-107 <br> https://fravoll.github.io/solidity-patterns/checks_effects_interactions.html <br>Recommendation:<br> The pattern of Checks Effects Interactions should be checked and analysed in order to prevent re-entrancy attacks. <br> <br><br> There are 13 instances of this issue:
<details><summary>see instances</summary>File: /packages/contracts/contracts/BorrowerOperations.sol range(211, 225): withdraws `_stEthBalanceDecrease` amount of collateral from the specified Cdp /// @dev If caller is different from Cdp owner, it will need approval from Cdp owner for this call /// @notice Successful execution is conditional on whether the withdrawal would bring down the ICR or TCR to the minimum requirement, e.g., MCR or CCR /// @param _cdpId The CdpId on which this operation is operated /// @param _stEthBalanceDecrease The total stETH collateral amount withdrawn (reduced) for the specified Cdp /// @param _upperHint The expected CdpId of neighboring higher ICR within SortedCdps, could be simply bytes32(0) /// @param _lowerHint The expected CdpId of neighboring lower ICR within SortedCdps, could be simply bytes32(0) function withdrawColl( bytes32 _cdpId, uint256 _stEthBalanceDecrease, bytes32 _upperHint, bytes32 _lowerHint ) external override nonReentrantSelfAndCdpM { _adjustCdpInternal(_cdpId, _stEthBalanceDecrease, 0, false, _upperHint, _lowerHint, 0); range(227, 241): withdraws `_debt` amount of eBTC token from the specified Cdp, thus increasing its debt accounting /// @dev If caller is different from Cdp owner, it will need approval from Cdp owner for this call /// @notice Successful execution is conditional on whether the withdrawal would bring down the ICR or TCR to the minimum requirement, e.g., MCR or CCR /// @param _cdpId The CdpId on which this operation is operated /// @param _debt The total debt collateral amount increased for the specified Cdp /// @param _upperHint The expected CdpId of neighboring higher ICR within SortedCdps, could be simply bytes32(0) /// @param _lowerHint The expected CdpId of neighboring lower ICR within SortedCdps, could be simply bytes32(0) function withdrawDebt( bytes32 _cdpId, uint256 _debt, bytes32 _upperHint, bytes32 _lowerHint ) external override nonReentrantSelfAndCdpM { _adjustCdpInternal(_cdpId, 0, _debt, true, _upperHint, _lowerHint, 0); range(259, 285): withdraws eBTC token and reduces stETH collateral) /// @notice or holding more safer position (repays eBTC token) with the specified Cdp. /// @notice If end user want to add collateral and change debt at the same time, use adjustCdpWithColl() instead /// @dev If caller is different from Cdp owner, it will need approval from Cdp owner for this call /// @param _cdpId The CdpId on which this operation is operated /// @param _stEthBalanceDecrease The total stETH collateral amount withdrawn from the specified Cdp /// @param _debtChange The total eBTC debt amount withdrawn or repaid for the specified Cdp /// @param _isDebtIncrease The flag (true or false) to indicate whether this is a eBTC token withdrawal (debt increase) or a repayment (debt reduce) /// @param _upperHint The expected CdpId of neighboring higher ICR within SortedCdps, could be simply bytes32(0) /// @param _lowerHint The expected CdpId of neighboring lower ICR within SortedCdps, could be simply bytes32(0) function adjustCdp( bytes32 _cdpId, uint256 _stEthBalanceDecrease, uint256 _debtChange, bool _isDebtIncrease, bytes32 _upperHint, bytes32 _lowerHint ) external override nonReentrantSelfAndCdpM { _adjustCdpInternal( _cdpId, _stEthBalanceDecrease, _debtChange, _isDebtIncrease, _upperHint, _lowerHint, 0 range(289, 316): withdraws eBTC token and reduces stETH collateral) /// @notice or holding more safer position (repays eBTC token and adds stETH collateral) with the specified Cdp. /// @dev If caller is different from Cdp owner, it will need approval from Cdp owner for this call /// @param _cdpId The CdpId on which this operation is operated /// @param _stEthBalanceDecrease The total stETH collateral amount withdrawn from the specified Cdp /// @param _debtChange The total eBTC debt amount withdrawn or repaid for the specified Cdp /// @param _isDebtIncrease The flag (true or false) to indicate whether this is a eBTC token withdrawal (debt increase) or a repayment (debt reduce) /// @param _upperHint The expected CdpId of neighboring higher ICR within SortedCdps, could be simply bytes32(0) /// @param _lowerHint The expected CdpId of neighboring lower ICR within SortedCdps, could be simply bytes32(0) /// @param _stEthBalanceIncrease The total stETH collateral amount deposited (added) for the specified Cdp function adjustCdpWithColl( bytes32 _cdpId, uint256 _stEthBalanceDecrease, uint256 _debtChange, bool _isDebtIncrease, bytes32 _upperHint, bytes32 _lowerHint, uint256 _stEthBalanceIncrease ) external override nonReentrantSelfAndCdpM { _adjustCdpInternal( _cdpId, _stEthBalanceDecrease, _debtChange, _isDebtIncrease, _upperHint, _lowerHint, _stEthBalanceIncrease range(321, 350): withdrawal. * * It therefore expects either a positive _stEthBalanceIncrease, or a positive _stEthBalanceDecrease argument. * * If both are positive, it will revert. */ function _adjustCdpInternal( bytes32 _cdpId, uint256 _stEthBalanceDecrease, uint256 _debtChange, bool _isDebtIncrease, bytes32 _upperHint, bytes32 _lowerHint, uint256 _stEthBalanceIncrease ) internal { // Confirm the operation is the borrower or approved position manager adjusting its own cdp address _borrower = sortedCdps.getOwnerAddress(_cdpId); _requireBorrowerOrPositionManagerAndUpdateManagerApproval(_borrower); _requireCdpisActive(cdpManager, _cdpId); cdpManager.syncAccounting(_cdpId); AdjustCdpLocals memory vars; vars.price = priceFeed.fetchPrice(); if (_isDebtIncrease) { _requireNonZeroDebtChange(_debtChange); range(369, 396): withdraw greater stEthBalance than the value in Cdp" ); vars.oldICR = EbtcMath._computeCR(_cdpStEthBalance, vars.debt, vars.price); vars.newICR = _getNewICRFromCdpChange( vars.collShares, vars.debt, vars.collSharesChange, vars.isCollIncrease, vars.netDebtChange, _isDebtIncrease, vars.price ); // Check the adjustment satisfies all conditions for the current system mode bool isRecoveryMode = _checkRecoveryModeForTCR(_getCachedTCR(vars.price)); _requireValidAdjustmentInCurrentMode( isRecoveryMode, _stEthBalanceDecrease, _isDebtIncrease, vars ); // When the adjustment is a debt repayment, check it's a valid amount, that the caller has enough EBTC, and that the resulting debt is >0 if (!_isDebtIncrease && _debtChange > 0) { _requireValidDebtRepayment(vars.debt, vars.netDebtChange); _requireSufficientEbtcTokenBalance(msg.sender, vars.netDebtChange); _requireNonZeroDebt(vars.debt - vars.netDebtChange); range(528, 546): withdrawDebt(msg.sender, _debt); /** Note that only NET stEth balance (as shares) is considered part of the Cdp. The static liqudiation incentive is stored in the gas pool and can be considered a deposit / voucher to be returned upon Cdp close, to the closer. The close can happen from the borrower closing their own Cdp, a full liquidation, or a redemption. */ // CEI: Move the collateral and liquidator gas compensation to the Active Pool. Track only net collateral for TCR purposes. _activePoolAddColl(_stEthBalance, _netCollAsShares); // Invariant check require( vars.netStEthBalance + LIQUIDATOR_REWARD == _stEthBalance, "BorrowerOperations: deposited collateral mismatch!" ); return _cdpId; range(548, 592): withdraw collateral, and close the specified Cdp /// @notice Caller should have enough eBTC token to repay off the debt fully for specified Cdp /// @dev If caller is different from Cdp owner, it will need approval from Cdp owner for this call /// @param _cdpId The CdpId on which this operation is operated function closeCdp(bytes32 _cdpId) external override { address _borrower = sortedCdps.getOwnerAddress(_cdpId); _requireBorrowerOrPositionManagerAndUpdateManagerApproval(_borrower); _requireCdpisActive(cdpManager, _cdpId); cdpManager.syncAccounting(_cdpId); uint256 price = priceFeed.fetchPrice(); _requireNotInRecoveryMode(_getCachedTCR(price)); uint256 collShares = cdpManager.getCdpCollShares(_cdpId); uint256 debt = cdpManager.getCdpDebt(_cdpId); uint256 liquidatorRewardShares = cdpManager.getCdpLiquidatorRewardShares(_cdpId); _requireSufficientEbtcTokenBalance(msg.sender, debt); uint256 newTCR = _getNewTCRFromCdpChange( collateral.getPooledEthByShares(collShares), false, debt, false, price ); _requireNewTCRisNotBelowCCR(newTCR); // == Grace Period == // // By definition we are not in RM, notify CDPManager to ensure "Glass is on" cdpManager.notifyEndGracePeriod(newTCR); cdpManager.closeCdp(_cdpId, _borrower, debt, collShares); // Burn the repaid EBTC from the user's balance _repayDebt(msg.sender, debt); // CEI: Send the collateral and liquidator reward shares back to the user activePool.transferSystemCollSharesAndLiquidatorReward( msg.sender, collShares, liquidatorRewardShares range(762, 763): withdraw range(789, 792): withdrawDebt(address _account, uint256 _debt) internal { activePool.increaseSystemDebt(_debt); ebtcToken.mint(_account, _debt); range(808, 809): withdraw range(847, 848): withdraw
</details>File: /packages/contracts/contracts/Interfaces/IBorrowerOperations.sol range(41, 86): withdrawColl( bytes32 _cdpId, uint256 _stEthBalanceDecrease, bytes32 _upperHint, bytes32 _lowerHint ) external; function withdrawDebt( bytes32 _cdpId, uint256 _amount, bytes32 _upperHint, bytes32 _lowerHint ) external; function repayDebt( bytes32 _cdpId, uint256 _amount, bytes32 _upperHint, bytes32 _lowerHint ) external; function closeCdp(bytes32 _cdpId) external; function adjustCdp( bytes32 _cdpId, uint256 _stEthBalanceDecrease, uint256 _debtChange, bool isDebtIncrease, bytes32 _upperHint, bytes32 _lowerHint ) external; function adjustCdpWithColl( bytes32 _cdpId, uint256 _stEthBalanceDecrease, uint256 _debtChange, bool isDebtIncrease, bytes32 _upperHint, bytes32 _lowerHint, uint256 _stEthBalanceIncrease ) external; function claimSurplusCollShares() external; function feeRecipientAddress() external view returns (address);
Description:<br>Creating a strong enough source of randomness in Ethereum is very challenging. For example, use of block.timestamp is insecure, as a miner can choose to provide any timestamp within a few seconds and still get his block accepted by others. Use of blockhash, block.difficulty and other fields is also insecure, as they're controlled by the miner. If the stakes are high, the miner can mine lots of blocks in a short time by renting hardware, pick the block that has required block hash for him to win, and drop all others.<br>https://swcregistry.io/docs/SWC-120 <br>Recommendation:<br>Using commitment scheme, e.g. RANDAO.<br>Using external sources of randomness via oracles, e.g. Oraclize. Note that this approach requires trusting in oracle, thus it may be reasonable to use multiple oracles. <br>Using Bitcoin block hashes, as they are more expensive to mine.<br><br> There are 18 instances of this issue:
<details><summary>see instances</summary>File: /packages/contracts/contracts/BorrowerOperations.sol 715: block.timestamp
File: /packages/contracts/contracts/CdpManager.sol 690: block.timestamp 691: block.timestamp 696: block.timestamp 698: block.timestamp 711: block.timestamp 712: block.timestamp
File: /packages/contracts/contracts/LiquidationLibrary.sol 94: block.timestamp
File: /packages/contracts/contracts/CdpManagerStorage.sol 53: block.timestamp 228: block.timestamp 542: block.timestamp 900: block.timestamp
File: /packages/contracts/contracts/EBTCToken.sol 208: block.timestamp
</details>File: /packages/contracts/contracts/PriceFeed.sol 381: block.timestamp 421: block.timestamp 423: block.timestamp 471: block.timestamp 494: block.timestamp
Description:<br> Solidity supports function types. That is, a variable of function type can be assigned with a reference to a function with a matching signature. The function saved to such variable can be called just like a regular function.The problem arises when a user has the ability to arbitrarily change the function type variable and thus execute random code instructions. As Solidity doesn't support pointer arithmetics, it's impossible to change such variable to an arbitrary value. However, if the developer uses assembly instructions, such as mstore or assign operator, in the worst case scenario an attacker is able to point a function type variable to any code instruction, violating required validations and required state changes.<br> https://swcregistry.io/docs/SWC-127 <br> <br>Recommendation:<br> The use of assembly should be minimal. A developer should not allow a user to assign arbitrary values to function type variables. <br><br> There is 1 instance of this issue:
<details><summary>see instance</summary></details>File: /packages/contracts/contracts/LeverageMacroBase.sol 529: mstore
Description:<br> TBD<br> <br><br>Recommendation:<br> TBD<br> <br><br> There are 80 instances of this issue:
<details><summary>see instances</summary>File: /packages/contracts/contracts/ActivePool.sol range(235, 236): (msg.sender == cdpManagerAddress, "ActivePool: Caller is not CdpManager") range(268, 269): (amount <= maxFlashLoan(token), "ActivePool: Too much") range(317, 318): (token == address(collateral), "ActivePool: collateral Only") range(373, 374): (token != address(collateral), "ActivePool: Cannot Sweep Collateral") range(376, 377): (amount <= balance, "ActivePool: Attempt to sweep more than balance") range(406, 407): (_newFee <= MAX_FEE_BPS, "ERC3156FlashLender: _newFee should <= MAX_FEE_BPS")
File: /packages/contracts/contracts/BorrowerOperations.sol range(144, 145): (locked == OPEN, "BorrowerOperations: Reentrancy in nonReentrant call") range(665, 666): () == _CACHED_CHAIN_ID) range(825, 826): (status == 1, "BorrowerOperations: Cdp does not exist or is closed") range(830, 831): (status == 0, "BorrowerOperations: Cdp is active or has been previously closed") range(1084, 1085): (amount <= maxFlashLoan(token), "BorrowerOperations: Too much") range(1114, 1115): (token == address(ebtcToken), "BorrowerOperations: EBTC Only") range(1154, 1155): (_newFee <= MAX_FEE_BPS, "ERC3156FlashLender: _newFee should <= MAX_FEE_BPS")
File: /packages/contracts/contracts/CdpManager.sol range(331, 332): (redemptionsPaused == false, "CdpManager: Redemptions Paused") range(368, 369): (currentBorrower != address(0) && getSyncedICR(_cId, totals.price) < MCR) range(496, 497): (_cnt > 0 && _id != bytes32(0)) range(501, 502): (_toRemoveIds[0] == _start, "CdpManager: batchRemoveSortedCdpIds check start error") range(677, 678): (decayedBaseRate <= DECIMAL_PRECISION, "CdpManager: baseRate too large!")
File: /packages/contracts/contracts/LiquidationLibrary.sol range(55, 56): (_partialAmount != 0, "LiquidationLibrary: use `liquidate` for 100%") range(602, 603): (toLiquidator == _totalColToSend) range(755, 756): (0) && Cdps[vars.cdpId].status == Status.active) range(818, 819): (0) && Cdps[vars.cdpId].status == Status.active)
File: /packages/contracts/contracts/CdpManagerStorage.sol range(145, 146): (1/2) = d^720 => d = (1/2)^(1/720) range(241, 242): (locked == OPEN, "CdpManager: Reentrancy in nonReentrant call") range(474, 475): (index <= idxLast, "CdpManagerStorage: CDP indexing overflow!") range(648, 649): (Cdps[_cdpId].status == Status.active, "CdpManager: Cdp does not exist or is closed")
File: /packages/contracts/contracts/CollSurplusPool.sol range(119, 120): (msg.sender == cdpManagerAddress, "CollSurplusPool: Caller is not CdpManager") range(123, 124): (msg.sender == activePoolAddress, "CollSurplusPool: Caller is not Active Pool") range(142, 143): (token != address(collateral), "CollSurplusPool: Cannot Sweep Collateral") range(145, 146): (amount <= balance, "CollSurplusPool: Attempt to sweep more than balance")
File: /packages/contracts/contracts/EBTCToken.sol range(182, 183): () == _CACHED_CHAIN_ID) range(218, 219): (recoveredAddress == owner, "EBTC: invalid signature") range(246, 247): (sender != address(0), "EBTCToken: zero sender!") range(247, 248): (recipient != address(0), "EBTCToken: zero recipient!") range(262, 263): (account != address(0), "EBTCToken: mint to zero recipient!") range(270, 271): (account != address(0), "EBTCToken: burn from zero account!") range(285, 286): (owner != address(0), "EBTCToken: zero approve owner!") range(286, 287): (spender != address(0), "EBTCToken: zero approve spender!") range(296, 297): (0) && _recipient != address(this) range(323, 324): (msg.sender == cdpManagerAddress, "EBTC: Caller is not CdpManager")
File: /packages/contracts/contracts/PriceFeed.sol range(223, 224): (fallbackCaller) == address(0)) range(586, 587): (fallbackCaller) != address(0))
File: /packages/contracts/contracts/SortedCdps.sol range(180, 181): (startNodeId == dummyId ? data.tail : startNodeId) range(184, 185): (_currentCdpId != dummyId) range(186, 187): (_currentCdpId) == owner) range(243, 244): (startNodeId == dummyId ? data.tail : startNodeId) range(247, 248): (_currentCdpId != dummyId) range(249, 250): (_currentCdpId) == owner) range(315, 316): (startNodeId == dummyId ? data.tail : startNodeId) range(317, 318): (_currentCdpId != dummyId) range(319, 320): (_currentCdpId) == owner) range(351, 352): (cdpManager.getCdpStatus(_id) == 0, "SortedCdps: new id is NOT nonExistent!") range(368, 369): (_id != dummyId, "SortedCdps: Id cannot be zero") range(519, 520): (data.head == _id || data.tail == _id) range(522, 523): (_node.nextId != dummyId && _node.prevId != dummyId) range(628, 629): (prevId != dummyId && !_validInsertPosition(_NICR, prevId, nextId)) range(651, 652): (nextId != dummyId && !_validInsertPosition(_NICR, prevId, nextId)) range(714, 715): (msg.sender == address(cdpManager), "SortedCdps: Caller is not the CdpManager")
File: /packages/contracts/contracts/LeverageMacroBase.sol range(44, 45): (owner() == msg.sender, "Must be owner") range(250, 251): (check.value <= valueToCheck, "!LeverageMacroReference: let post check") range(252, 253): (check.value == valueToCheck, "!LeverageMacroReference: equal post check") range(351, 352): (initiator == address(this), "LeverageMacroReference: wrong initiator for flashloan") range(451, 452): (addy != address(borrowerOperations)) range(452, 453): (addy != address(sortedCdps)) range(453, 454): (addy != address(activePool)) range(454, 455): (addy != address(cdpManager)) range(455, 456): (addy != address(this))
File: /packages/contracts/contracts/SimplifiedDiamondLike.sol range(51, 52): (msg.sender == owner) range(55, 56): (sig != 0x94b24d09) range(66, 67): (msg.sender == owner) range(76, 77): (msg.sender == address(this)) range(110, 111): (msg.sender == owner, "Must be owner") range(186, 187): (facet != address(0), "Diamond: Function does not exist")
File: /packages/contracts/contracts/Dependencies/Auth.sol range(37, 38): (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) range(44, 45): (msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig))
File: /packages/contracts/contracts/Dependencies/AuthNoOwner.sol range(34, 35): (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) range(55, 56): (address(_authority) == address(0), "Auth: authority is non-zero")
File: /packages/contracts/contracts/Dependencies/EbtcBase.sol range(108, 109): (feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum")
File: /packages/contracts/contracts/Dependencies/ReentrancyGuard.sol range(13, 14): (locked == OPEN, "ReentrancyGuard: Reentrancy in nonReentrant call")
</details>File: /packages/contracts/contracts/Dependencies/RolesAuthority.sol range(123, 124): () == 0)
Description:<br> Several functions and operators in Solidity are deprecated. Using them leads to reduced code quality. With new major versions of the Solidity compiler, deprecated functions and operators may result in side effects and compile errors. https://swcregistry.io/docs/SWC-111 <br> <br>Recommendation:<br> Solidity provides alternatives to the deprecated constructions. Most of them are aliases, thus replacing old constructions will not break current behavior. <br> <br><br> There are 48 instances of this issue:
<details><summary>see instances</summary>File: /packages/contracts/contracts/ActivePool.sol 24: string public constant NAME = "ActivePool";
File: /packages/contracts/contracts/BorrowerOperations.sol 29: string public constant NAME = "BorrowerOperations"; 32: bytes32 private constant _PERMIT_POSITION_MANAGER_TYPEHASH = 38: bytes32 private constant _TYPE_HASH = 41: string internal constant _VERSION = "1";
File: /packages/contracts/contracts/CdpManagerStorage.sol 21: uint128 public constant UNSET_TIMESTAMP = type(uint128).max; 22: uint128 public constant MINIMUM_GRACE_PERIOD = 15 minutes; 122: string public constant NAME = "CdpManager"; 139: uint256 public constant SECONDS_IN_ONE_MINUTE = 60; 141: uint256 public constant MIN_REDEMPTION_FEE_FLOOR = (DECIMAL_PRECISION * 5) / 1000; // 0.5% 149: uint256 public constant MIN_MINUTE_DECAY_FACTOR = 1; // Non-zero 150: uint256 public constant MAX_MINUTE_DECAY_FACTOR = 999999999999999999; // Corresponds to a very fast decay rate, but not too extreme
File: /packages/contracts/contracts/CollSurplusPool.sol 19: string public constant NAME = "CollSurplusPool";
File: /packages/contracts/contracts/EBTCToken.sol 28: string internal constant _NAME = "EBTC Stablecoin"; 29: string internal constant _SYMBOL = "EBTC"; 30: string internal constant _VERSION = "1"; 31: uint8 internal constant _DECIMALS = 18; 36: bytes32 private constant _PERMIT_TYPEHASH = 39: bytes32 private constant _TYPE_HASH =
File: /packages/contracts/contracts/PriceFeed.sol 22: string public constant NAME = "PriceFeed"; 32: uint256 public constant TIMEOUT_ETH_BTC_FEED = 4800; // 1 hours & 20min: 60 * 80 33: uint256 public constant TIMEOUT_STETH_ETH_FEED = 90000; // 25 hours: 60 * 60 * 25 36: uint256 public constant MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND = 5e17; // 50% 42: uint256 public constant MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES = 5e16; // 5%
File: /packages/contracts/contracts/SortedCdps.sol 52: string public constant NAME = "SortedCdps"; 60: uint256 constant ADDRESS_SHIFT = 96; // 8 * 12; Puts the address at leftmost bytes32 position 61: uint256 constant BLOCK_SHIFT = 64; // 8 * 8; Puts the block value after the address 80: bytes32 public constant dummyId =
File: /packages/contracts/contracts/HintHelpers.sol 12: string public constant NAME = "HintHelpers";
File: /packages/contracts/contracts/LeverageMacroBase.sol 37: bytes32 constant FLASH_LOAN_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
File: /packages/contracts/contracts/SimplifiedDiamondLike.sol 39: bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");
File: /packages/contracts/contracts/Dependencies/ERC3156FlashLender.sol 9: uint256 public constant MAX_BPS = 10_000; 10: uint256 public constant MAX_FEE_BPS = 1_000; // 10% 11: bytes32 public constant FLASH_SUCCESS_VALUE = keccak256("ERC3156FlashBorrower.onFlashLoan");
File: /packages/contracts/contracts/Dependencies/EbtcBase.sol 19: uint256 public constant LICR = 1030000000000000000; // 103% 22: uint256 public constant MCR = 1100000000000000000; // 110% 25: uint256 public constant CCR = 1250000000000000000; // 125% 28: uint256 public constant LIQUIDATOR_REWARD = 2e17; 31: uint256 public constant MIN_NET_STETH_BALANCE = 2e18; 33: uint256 public constant PERCENT_DIVISOR = 200; // dividing by 200 yields 0.5% 35: uint256 public constant BORROWING_FEE_FLOOR = 0; // 0.5% 37: uint256 public constant STAKING_REWARD_SPLIT = 5_000; // taking 50% cut from staking reward 39: uint256 public constant MAX_REWARD_SPLIT = 10_000;
File: /packages/contracts/contracts/Dependencies/EbtcMath.sol 6: uint256 internal constant DECIMAL_PRECISION = 1e18; 7: uint256 public constant MAX_TCR = type(uint256).max; 18: uint256 internal constant NICR_PRECISION = 1e20;
</details>File: /packages/contracts/contracts/Dependencies/ReentrancyGuard.sol 8: uint256 internal constant OPEN = 1; 9: uint256 internal constant LOCKED = 2;
Description:<br> Comparison will be ignored.<br> <br><br>Recommendation:<br> Use require or if to compare values.<br> <br><br> There are 80 instances of this issue:
<details><summary>see instances</summary>File: /packages/contracts/contracts/ActivePool.sol range(235, 236): (msg.sender == cdpManagerAddress, "ActivePool: Caller is not CdpManager") range(268, 269): (amount <= maxFlashLoan(token), "ActivePool: Too much") range(317, 318): (token == address(collateral), "ActivePool: collateral Only") range(373, 374): (token != address(collateral), "ActivePool: Cannot Sweep Collateral") range(376, 377): (amount <= balance, "ActivePool: Attempt to sweep more than balance") range(406, 407): (_newFee <= MAX_FEE_BPS, "ERC3156FlashLender: _newFee should <= MAX_FEE_BPS")
File: /packages/contracts/contracts/BorrowerOperations.sol range(144, 145): (locked == OPEN, "BorrowerOperations: Reentrancy in nonReentrant call") range(665, 666): () == _CACHED_CHAIN_ID) range(825, 826): (status == 1, "BorrowerOperations: Cdp does not exist or is closed") range(830, 831): (status == 0, "BorrowerOperations: Cdp is active or has been previously closed") range(1084, 1085): (amount <= maxFlashLoan(token), "BorrowerOperations: Too much") range(1114, 1115): (token == address(ebtcToken), "BorrowerOperations: EBTC Only") range(1154, 1155): (_newFee <= MAX_FEE_BPS, "ERC3156FlashLender: _newFee should <= MAX_FEE_BPS")
File: /packages/contracts/contracts/CdpManager.sol range(331, 332): (redemptionsPaused == false, "CdpManager: Redemptions Paused") range(368, 369): (currentBorrower != address(0) && getSyncedICR(_cId, totals.price) < MCR) range(496, 497): (_cnt > 0 && _id != bytes32(0)) range(501, 502): (_toRemoveIds[0] == _start, "CdpManager: batchRemoveSortedCdpIds check start error") range(677, 678): (decayedBaseRate <= DECIMAL_PRECISION, "CdpManager: baseRate too large!")
File: /packages/contracts/contracts/LiquidationLibrary.sol range(55, 56): (_partialAmount != 0, "LiquidationLibrary: use `liquidate` for 100%") range(602, 603): (toLiquidator == _totalColToSend) range(755, 756): (0) && Cdps[vars.cdpId].status == Status.active) range(818, 819): (0) && Cdps[vars.cdpId].status == Status.active)
File: /packages/contracts/contracts/CdpManagerStorage.sol range(145, 146): (1/2) = d^720 => d = (1/2)^(1/720) range(241, 242): (locked == OPEN, "CdpManager: Reentrancy in nonReentrant call") range(474, 475): (index <= idxLast, "CdpManagerStorage: CDP indexing overflow!") range(648, 649): (Cdps[_cdpId].status == Status.active, "CdpManager: Cdp does not exist or is closed")
File: /packages/contracts/contracts/CollSurplusPool.sol range(119, 120): (msg.sender == cdpManagerAddress, "CollSurplusPool: Caller is not CdpManager") range(123, 124): (msg.sender == activePoolAddress, "CollSurplusPool: Caller is not Active Pool") range(142, 143): (token != address(collateral), "CollSurplusPool: Cannot Sweep Collateral") range(145, 146): (amount <= balance, "CollSurplusPool: Attempt to sweep more than balance")
File: /packages/contracts/contracts/EBTCToken.sol range(182, 183): () == _CACHED_CHAIN_ID) range(218, 219): (recoveredAddress == owner, "EBTC: invalid signature") range(246, 247): (sender != address(0), "EBTCToken: zero sender!") range(247, 248): (recipient != address(0), "EBTCToken: zero recipient!") range(262, 263): (account != address(0), "EBTCToken: mint to zero recipient!") range(270, 271): (account != address(0), "EBTCToken: burn from zero account!") range(285, 286): (owner != address(0), "EBTCToken: zero approve owner!") range(286, 287): (spender != address(0), "EBTCToken: zero approve spender!") range(296, 297): (0) && _recipient != address(this) range(323, 324): (msg.sender == cdpManagerAddress, "EBTC: Caller is not CdpManager")
File: /packages/contracts/contracts/PriceFeed.sol range(223, 224): (fallbackCaller) == address(0)) range(586, 587): (fallbackCaller) != address(0))
File: /packages/contracts/contracts/SortedCdps.sol range(180, 181): (startNodeId == dummyId ? data.tail : startNodeId) range(184, 185): (_currentCdpId != dummyId) range(186, 187): (_currentCdpId) == owner) range(243, 244): (startNodeId == dummyId ? data.tail : startNodeId) range(247, 248): (_currentCdpId != dummyId) range(249, 250): (_currentCdpId) == owner) range(315, 316): (startNodeId == dummyId ? data.tail : startNodeId) range(317, 318): (_currentCdpId != dummyId) range(319, 320): (_currentCdpId) == owner) range(351, 352): (cdpManager.getCdpStatus(_id) == 0, "SortedCdps: new id is NOT nonExistent!") range(368, 369): (_id != dummyId, "SortedCdps: Id cannot be zero") range(519, 520): (data.head == _id || data.tail == _id) range(522, 523): (_node.nextId != dummyId && _node.prevId != dummyId) range(628, 629): (prevId != dummyId && !_validInsertPosition(_NICR, prevId, nextId)) range(651, 652): (nextId != dummyId && !_validInsertPosition(_NICR, prevId, nextId)) range(714, 715): (msg.sender == address(cdpManager), "SortedCdps: Caller is not the CdpManager")
File: /packages/contracts/contracts/LeverageMacroBase.sol range(44, 45): (owner() == msg.sender, "Must be owner") range(250, 251): (check.value <= valueToCheck, "!LeverageMacroReference: let post check") range(252, 253): (check.value == valueToCheck, "!LeverageMacroReference: equal post check") range(351, 352): (initiator == address(this), "LeverageMacroReference: wrong initiator for flashloan") range(451, 452): (addy != address(borrowerOperations)) range(452, 453): (addy != address(sortedCdps)) range(453, 454): (addy != address(activePool)) range(454, 455): (addy != address(cdpManager)) range(455, 456): (addy != address(this))
File: /packages/contracts/contracts/SimplifiedDiamondLike.sol range(51, 52): (msg.sender == owner) range(55, 56): (sig != 0x94b24d09) range(66, 67): (msg.sender == owner) range(76, 77): (msg.sender == address(this)) range(110, 111): (msg.sender == owner, "Must be owner") range(186, 187): (facet != address(0), "Diamond: Function does not exist")
File: /packages/contracts/contracts/Dependencies/Auth.sol range(37, 38): (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) range(44, 45): (msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig))
File: /packages/contracts/contracts/Dependencies/AuthNoOwner.sol range(34, 35): (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) range(55, 56): (address(_authority) == address(0), "Auth: authority is non-zero")
File: /packages/contracts/contracts/Dependencies/EbtcBase.sol range(108, 109): (feePercentage <= _maxFeePercentage, "Fee exceeded provided maximum")
File: /packages/contracts/contracts/Dependencies/ReentrancyGuard.sol range(13, 14): (locked == OPEN, "ReentrancyGuard: Reentrancy in nonReentrant call")
</details>File: /packages/contracts/contracts/Dependencies/RolesAuthority.sol range(123, 124): () == 0)
Description:<br> Prior to solidity version 0.8.0, hitting an assert consumes the remainder of the transaction\βs available gas rather than returning it, as require()/revert() do. assert() should be avoided even past solidity version 0.8.0 as its documentation states that βThe assert function creates an error of type Panic(uint256). β¦ Properly functioning code should never create a Panic, not even on invalid external input. If this happens, then there is a bug in your contract which you should fixβ. https://swcregistry.io/docs/SWC-110/ <br> <br>Recommendation:<br> Consider whether the condition checked in the assert() is actually an invariant.If not, replace the assert() statement with a require() statement. If the exception is indeed caused by unexpected behaviour of the code, fix the underlying bug(s) that allow the assertion to be violated. <br> <br><br> There are 6 instances of this issue:
<details><summary>see instances</summary>File: /packages/contracts/contracts/LiquidationLibrary.sol 564: assert(toLiquidator < _totalColToSend); // Assert is correct here for Echidna
File: /packages/contracts/contracts/LeverageMacroBase.sol 43: function _assertOwner() internal { 125: _assertOwner(); 215: _assertOwner(); 235: _assertOwner();
</details>File: /packages/contracts/contracts/LeverageMacroReference.sol 51: _assertOwner();
#0 - c4-pre-sort
2023-11-18T00:58:30Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-12-01T16:28:08Z
fatherGoose1 marked the issue as grade-b