Platform: Code4rena
Start Date: 21/02/2024
Pot Size: $200,000 USDC
Total HM: 22
Participants: 36
Period: 19 days
Judge: Trust
Total Solo HM: 12
Id: 330
League: ETH
Rank: 33/36
Findings: 1
Award: $123.08
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xAnah
Also found by: 0x11singh99, 0xhacksmithh, K42, albahaca, dharma09
123.0826 USDC - $123.08
checks
should be moved to the top of functionSo that it will revert eailer before state read.
file: MainHelper.sol
function _checkLiquidatorNft( uint256 _nftId, uint256 _nftIdLiquidator ) internal view { + if (_nftIdLiquidator == _nftId) { + revert InvalidLiquidator(); + } if (positionLocked[_nftIdLiquidator] == true) { revert LiquidatorIsInPowerFarm(); } - if (_nftIdLiquidator == _nftId) { - revert InvalidLiquidator(); - } if (_nftIdLiquidator >= POSITION_NFT.getNextExpectedId()) { revert InvalidLiquidator(); }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/MainHelper.sol#L265-L275
_compareMinMax()
could be re arranged to save gasBefore
maxAnswer
& minAnswer
After
file : OracleHelper.sol
function _compareMinMax( IAggregator _tokenAggregator, int192 _answer ) internal view { - int192 maxAnswer = _tokenAggregator.maxAnswer(); - int192 minAnswer = _tokenAggregator.minAnswer(); - if (_answer > maxAnswer || _answer < minAnswer) { - revert OracleIsDead(); - } + int192 maxAnswer = _tokenAggregator.maxAnswer(); + if (_answer > maxAnswer){ + revert OracleIsDead(); + } + int192 minAnswer = _tokenAggregator.minAnswer(); + if (_answer < minAnswer) { + revert OracleIsDead(); + } }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracleHub/OracleHelper.sol#L94-L99
File : PendleLpOracle.sol
One extra storage slot saved here
IPendleSy public immutable PENDLE_SY; IPriceFeed public immutable FEED_ASSET; IOraclePendle public immutable ORACLE_PENDLE_PT; uint8 internal constant FEED_DECIMALS = 18; + uint32 public immutable TWAP_DURATION; uint256 internal constant POW_FEED_DECIMALS = 10 ** 18; // Precision factor for computations. uint256 internal constant PRECISION_FACTOR_E18 = 1E18; // -- Twap duration in seconds --- - uint32 public immutable TWAP_DURATION; // -- Farm description -- string public name;
file : WiseLending.sol
{ + uint256 _powerFarmCheck = powerFarmCheck; _checkHealthState( _nftId, - powerFarmCheck + _powerFarmCheck ); if (powerFarmCheck == true) { - powerFarmCheck = false; + _powerFarmCheck = false; } }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L82-L89
borrowPoolData[_poolToken]
& lendingPoolData[_poolToken]
could be cached in memory- uint256 borrowSharePrice = borrowPoolData[_poolToken].pseudoTotalBorrowAmount * PRECISION_FACTOR_E18 / borrowPoolData[_poolToken].totalBorrowShares; _validateParameter( MIN_BORROW_SHARE_PRICE, borrowSharePrice ); return ( lendingPoolData[_poolToken].pseudoTotalPool * PRECISION_FACTOR_E18 / lendingPoolData[_poolToken].totalDepositShares, borrowSharePrice );
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L175-L189
WISE_SECURITY
could be cached rather than re-calling it 2 timesdata.maxFeeETH = WISE_SECURITY.maxFeeETH(); // @audit cache WISE_SECURITY data.baseRewardLiquidation = WISE_SECURITY.baseRewardLiquidation();
function setRegistrationIsolationPool( uint256 _nftId, bool _registerState ) external { _onlyIsolationPool( msg.sender ); _validateZero( WISE_SECURITY.overallETHCollateralsBare(_nftId) // @audit WISE_SECURITY ); _validateZero( WISE_SECURITY.overallETHBorrowBare(_nftId) );
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L1273-L1274 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L1397-L1401
WISE_LENDING
should be cachedfile : WiseSecurity.sol
if (WISE_LENDING.verifiedIsolationPool(_caller) == true) { // @audit WISE_LENDING return true; } if (WISE_LENDING.positionLocked(_nftId) == true) { return true; } if (_isUncollateralized(_nftId, _poolToken) == true) { return true; } if (WISE_LENDING.getPositionBorrowTokenLength(_nftId) == 0) { return true; }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L255-L269
if (WISE_LENDING.verifiedIsolationPool(_caller) == true) { return true; } if (WISE_LENDING.positionLocked(_nftId) == true) { return true; }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L293-L297
WISE_SECURITY
could be cachedfile : WiseLendingDeclaration.sol
if (address(WISE_SECURITY) > ZERO_ADDRESS) { revert InvalidAction(); } WISE_SECURITY = IWiseSecurity( _wiseSecurity ); FEE_MANAGER = IFeeManagerLight( WISE_SECURITY.FEE_MANAGER() // @audit G:: 2 state read can avoid here by using _wiseSecurity ); AAVE_HUB_ADDRESS = WISE_SECURITY.AAVE_HUB(); }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLendingDeclaration.sol#L146-L156
POSITION_NFT
could be cacheduint256 nftId = POSITION_NFT.mintPosition(); _registrationFarm( nftId ); POSITION_NFT.approve( AAVE_HUB_ADDRESS, nftId );
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/PowerFarms/PendlePowerFarm/PendlePowerManager.sol#L191-L200
incentiveOwnerA
& incentiveOwnerB
could be cachedfile : FeeManager.sol
One extra storage read saved.
if (msg.sender != incentiveOwnerA) { // @audit G:: cache incentiveOwnerA revert NotAllowed(); } if (_newOwner == incentiveOwnerA) { revert NotAllowed(); } if (_newOwner == incentiveOwnerB) { revert NotAllowed(); } incentiveUSD[_newOwner] = incentiveUSD[ incentiveOwnerA ]; delete incentiveUSD[ incentiveOwnerA ]; incentiveOwnerA = _newOwner;
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L320-L340
if (msg.sender != incentiveOwnerB) { // @audit chache incentiveOwnerB revert NotAllowed(); } if (_newOwner == incentiveOwnerA) { revert NotAllowed(); } if (_newOwner == incentiveOwnerB) { revert NotAllowed(); } incentiveUSD[_newOwner] = incentiveUSD[ incentiveOwnerB ]; delete incentiveUSD[ incentiveOwnerB ]; incentiveOwnerB = _newOwner; emit IncentiveOwnerBChanged( _newOwner, block.timestamp ); }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L357-L377
file : WiseLending.sol
{ - uint256 shareAmount = _handleDeposit( - msg.sender, - _nftId, - _poolToken, - _amount - ); _safeTransferFrom( _poolToken, msg.sender, address(this), _amount ); - return shareAmount; + return _handleDeposit( + msg.sender, + _nftId, + _poolToken, + _amount + ); }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L407-L418
timeSinceUp
variablefile: OracleHelper.sol
- uint256 timeSinceUp = block.timestamp - startedAt; - if (timeSinceUp <= GRACE_PEROID) { + if(block.timestamp - startedAt <= GRACE_PEROID) return true; }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracleHub/OracleHelper.sol#L541-L546
curveSwapInfoData[_poolToken]
could be cachedfile : WiseSecurity.sol
address curvePool = curveSwapInfoData[_poolToken].curvePool; // @audit cache curveSwapInfoData[_poolToken] if (curvePool == ZERO_ADDRESS) { return; } ( bool success , ) = curvePool.call{value: 0} ( curveSwapInfoData[_poolToken].swapBytesPool ); _checkSuccess( success ); address curveMeta = curveSwapInfoData[_poolToken].curveMetaPool; if (curveMeta == ZERO_ADDRESS) { return; } ( success , ) = curveMeta.call{value: 0} ( curveSwapInfoData[_poolToken].swapBytesMeta );
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L199-L226
incentiveUSD[_incentiveOwner]
could be cachedfile: FeeManagerHelper.sol
uint256 reduceUSD = usdEquivalent < incentiveUSD[_incentiveOwner] ? usdEquivalent : incentiveUSD[_incentiveOwner];
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManagerHelper.sol#L348-L350
borrowPoolData[_poolToken]
& lendingPoolData[_poolToken]
could be cachedfile : MainHelper.sol
return _calculateShares( borrowPoolData[_poolToken].totalBorrowShares * _amount, borrowPoolData[_poolToken].pseudoTotalBorrowAmount, _maxSharePrice );
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/MainHelper.sol#L65-L66 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/MainHelper.sol#L102-L103 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/MainHelper.sol#L123-L125 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/MainHelper.sol#L507-L510
WISE_LENDING
& WISE_ORACLE
should be cached outside of loopfile : WiseSecurity.sol
while (i < len) { token = WISE_LENDING.getPositionLendingTokenByIndex( //@audit loop state variable call _nftId, i ); amount = getPositionLendingAmount( _nftId, token ); ethValue = WISE_ORACLE.getTokensInETH( token, amount ); weightedRate += ethValue * getLendingRate(token); overallETH += ethValue; unchecked { ++i; }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L466 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L476 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L523 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L533 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L582 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L662 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L679 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L711 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L763
WISE_LENDING
could cached outside the loopfile : FeeManager.sol
while (i < l) { _checkValue( _newFees[i] ); WISE_LENDING.setPoolFee( _poolTokens[i], _newFees[i] );
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L145-L154
WISE_LENDING
could cachedfile : AaveHelper.sol
for (i; i < l;) { address currentAddress = WISE_LENDING.getPositionLendingTokenByIndex( _nftId, i ); unchecked { ++i; } if (currentAddress == _poolToken) { continue; } WISE_LENDING.preparePool( // @audit currentAddress ); WISE_LENDING.newBorrowRate( _poolToken ); }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WrapperHub/AaveHelper.sol#L254-L274
immutable
WISE_SECURITY
, POSITION_NFT
& AAVE_HUB_ADDRESS
could be immutablefile : WiseLendingDeclaration.sol
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLendingDeclaration.sol#L162 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLendingDeclaration.sol#L174 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLendingDeclaration.sol#L180
file : FeeManager.sol
function setAaveFlagBulk( address[] calldata _poolTokens, address[] calldata _underlyingTokens ) external onlyMaster { uint256 i; uint256 l = _poolTokens.length; // @audit length same or not not checked while (i < l) { _setAaveFlag( _poolTokens[i], _underlyingTokens[i] ); unchecked { ++i; } }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L90-L96 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L143-L154
proposedIncentiveMaster
, msg.sender
could usedfile : FeeManager.sol
One extra storage read saved.
function claimOwnershipIncentiveMaster() external { if (msg.sender != proposedIncentiveMaster) { revert NotAllowed(); } - incentiveMaster = proposedIncentiveMaster; + incentiveMaster = msg.sender; proposedIncentiveMaster = ZERO_ADDRESS;
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L90-L96
msg.sender
into memory variable, rather using directly cost less gasfile : FeeManager.sol
- address caller = msg.sender; if (totalBadDebtETH > 0) { revert ExistingBadDebt(); } if (allowedTokens[caller][_feeToken] == false) { revert NotAllowed(); } _decreaseFeeTokens( _feeToken, _amount ); _safeTransfer( _feeToken, - caller, + msg.sender, _amount ); emit ClaimedFeesBeneficial( - caller, + msg.sender, _feeToken, _amount, block.timestamp );
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L695 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L712 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/FeeManager/FeeManager.sol#L717
MAX_COLLATERAL_FACTOR
should be a value and following comment explains how this result calculated from an expressionFile : PendlePowerFarmDeclaration.sol
uint256 internal constant MAX_COLLATERAL_FACTOR = 95 * PRECISION_FACTOR_E16;
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/PowerFarms/PendlePowerFarm/PendlePowerFarmDeclarations.sol#L62
sendingProgressAaveHub
should writed after success
variable checkIf success
condition true then whole Tx failed and gas wasted by writing to sendingProgressAaveHub
file : AaveHelper.sol
function _sendValue( address _recipient, uint256 _amount ) internal { if (address(this).balance < _amount) { revert InvalidValue(); } sendingProgressAaveHub = true; (bool success, ) = payable(_recipient).call{ value: _amount }(""); + if (success == false) { + revert FailedInnerCall(); + } sendingProgressAaveHub = false; - if (success == false) { - revert FailedInnerCall(); - }
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WrapperHub/AaveHelper.sol#L196-L216
#0 - c4-pre-sort
2024-03-17T10:48:28Z
GalloDaSballo marked the issue as insufficient quality report
#1 - c4-judge
2024-03-26T11:18:42Z
trust1995 marked the issue as grade-b