Platform: Code4rena
Start Date: 16/02/2023
Pot Size: $144,750 USDC
Total HM: 17
Participants: 154
Period: 19 days
Judge: Trust
Total Solo HM: 5
Id: 216
League: ETH
Rank: 72/154
Findings: 1
Award: $61.26
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: GalloDaSballo
Also found by: 0x3b, 0xAgro, 0xSmartContract, 0xTheC0der, 0xackermann, 0xnev, 0xsomeone, ABA, BRONZEDISC, Bjorn_bug, Bnke0x0, Breeje, Co0nan, CodeFoxInc, CodingNameKiki, DadeKuma, DeFiHackLabs, IceBear, Josiah, Kaysoft, Lavishq, MohammedRizwan, PaludoX0, PawelK, Phantasmagoria, Raiders, RaymondFam, Rickard, Rolezn, Sathish9098, SleepingBugs, SuperRayss, UdarTeam, Udsen, Viktor_Cortess, arialblack14, ast3ros, bin2chen, brgltd, btk, catellatech, ch0bu, chaduke, chrisdior4, codeislight, cryptonue, delfin454000, descharre, dontonka, emmac002, fs0c, hacker-dom, hansfriese, imare, lukris02, luxartvinsec, martin, matrix_0wl, peanuts, rbserver, shark, tnevler, trustindistrust, tsvetanovv, vagrant, yongskiws, zzzitron
61.2601 USDC - $61.26
Context:
return singleLiquidation;
L353return zeroVals;
L433return singleLiquidation;
L436return newTotals;
L912return _addTroveOwnerToArray(_borrower, _collateral);
L1318return index;
L1332return (collGainPerUnitStaked, LUSDLossPerUnitStaked);
L543return _getCollateralGainFromSnapshots(initialDeposit, snapshots);
L632return address(token);
L30return balance();
L38return (assets * totalSupply()) / _freeFunds();
L53return (shares * _freeFunds()) / totalSupply();
L68if (tvlCap == type(uint256).max) return type(uint256).max;
L81return tvlCap - balance();
L82return convertToShares(assets);
L97shares = _deposit(assets, receiver);
L111if (tvlCap == type(uint256).max) return type(uint256).max;
L124if (totalSupply() == 0) return shares;
L140return convertToAssets(balanceOf(owner));
L166if (totalSupply() == 0 || _freeFunds() == 0) return 0;
L184return balanceOf(owner);
L221return convertToAssets(shares);
L241return balanceOfWant();
L106Recommendation:
Choose named return variable or return statement. It is unnecessary to use both.
Context:
bytes32 public constant DEPOSITOR = keccak256("DEPOSITOR");
L73bytes32 public constant STRATEGIST = keccak256("STRATEGIST");
L74bytes32 public constant GUARDIAN = keccak256("GUARDIAN");
L75bytes32 public constant ADMIN = keccak256("ADMIN");
L76bytes32 public constant KEEPER = keccak256("KEEPER");
L49bytes32 public constant STRATEGIST = keccak256("STRATEGIST");
L50bytes32 public constant GUARDIAN = keccak256("GUARDIAN");
L51bytes32 public constant ADMIN = keccak256("ADMIN");
L52Description:
According to official solidity documentation for a constant variable, the expression assigned to it is copied to all the places where it is accessed and also re-evaluated each time. It is recommended to use immutable instead.
Context:
uint LUSDLoss = initialDeposit.sub(compoundedLUSDDeposit); // Needed only for event log
L384
Context:
struct LocalVariables_adjustTrove {
L47struct LocalVariables_openTrove {
L66mapping (address => uint256) internal collAmount; // collateral => amount tracker
L41 (collAmount should start with _)mapping (address => uint256) internal LUSDDebt; // collateral => corresponding debt tracker
L42 (LUSDDebt should start with _)mapping (address => uint256) internal collAmounts; // deposited collateral tracker
L167 (collAmounts should start with _)uint256 internal totalLUSDDeposits;
L170 (totalLUSDSeposits should start with _)mapping (address => uint) public lastCollateralError_Offset;
L228 (Variable name must be in mixedCase)uint public lastLUSDLossError_Offset;
L229 (Variable name must be in mixedCase)function depositSnapshots_S(address _depositor, address _collateral) external override view returns (uint) {
L410 (Function name must be in mixedCase)IERC20 public OathToken;
L37 (Variable name must be in mixedCase)function sendOath(address _account, uint _OathAmount) external override {
L124 (Variable name _OathAmount must be in mixedCase)function increaseF_Collateral(address _collateral, uint _collFee) external override {
L177 (Function name must be in mixedCase)function increaseF_LUSD(uint _LUSDFee) external override {
L187 (Function name must be in mixedCase)function roundUpDiv(uint256 x, uint256 y) internal pure returns (uint256) {
L269 (roundUpDiv should start with _)uint16 private constant LENDER_REFERRAL_CODE_NONE = 0;
L35 (LENDER_REFERRAL_CODE_NONE should start with _)Description:
The above codes don't follow Solidity's standard naming convention.
Context:
function sendCollateral(address _collateral, address _account, uint _amount) external override {
L171 (external function can not go after external view function)function setWithdrawalQueue(address[] calldata _withdrawalQueue) external {
L258 (extarnal function can not go after public function)function maxDeposit(address) external view override returns (uint256 maxAssets) {
L79 (external function can not go after public function)function updateVeloSwapPath(
L147 (external function can not go after internal function)Description:
According to official solidity documentation functions should be grouped according to their visibility and ordered:
constructor
receive function (if exists)
fallback function (if exists)
external
public
internal
private
Within a grouping, place the view and pure functions last.
Recommendation:
Put the functions in the correct order according to the documentation.
Context:
All contracts.
Description:
https://docs.soliditylang.org/en/v0.8.19/natspec-format.html
Recommendation:
Increase NatSpec comments in all contracts.
Context:
event TroveUpdated(address indexed _borrower, address _collateral, uint _debt, uint _coll, uint stake, BorrowerOperation operation);
L105function openTrove(address _collateral, uint _collAmount, uint _maxFeePercentage, uint _LUSDAmount, address _upperHint, address _lowerHint) external override {
L172vars.LUSDFee = _triggerBorrowingFee(contractsCache.troveManager, contractsCache.lusdToken, _LUSDAmount, _maxFeePercentage);
L190_withdrawLUSD(contractsCache.activePool, contractsCache.lusdToken, _collateral, msg.sender, _LUSDAmount, vars.netDebt);
L233_withdrawLUSD(contractsCache.activePool, contractsCache.lusdToken, _collateral, gasPoolAddress, LUSD_GAS_COMPENSATION, LUSD_GAS_COMPENSATION);
L235emit TroveUpdated(msg.sender, _collateral, vars.compositeDebt, _collAmount, vars.stake, BorrowerOperation.openTrove);
L237function moveCollateralGainToTrove(address _borrower, address _collateral, uint _collAmount, address _upperHint, address _lowerHint) external override {
L248function withdrawColl(address _collateral, uint _collWithdrawal, address _upperHint, address _lowerHint) external override {
L254function withdrawLUSD(address _collateral, uint _maxFeePercentage, uint _LUSDAmount, address _upperHint, address _lowerHint) external override {
L259function repayLUSD(address _collateral, uint _LUSDAmount, address _upperHint, address _lowerHint) external override {
L264function adjustTrove(address _collateral, uint _maxFeePercentage, uint _collTopUp, uint _collWithdrawal, uint _LUSDChange, bool _isDebtIncrease, address _upperHint, address _lowerHint) external override {
L268_adjustTrove(msg.sender, _collateral, _collTopUp, _collWithdrawal, _LUSDChange, _isDebtIncrease, _upperHint, _lowerHint, _maxFeePercentage);
L272function _adjustTrove(address _borrower, address _collateral, uint _collTopUp, uint _collWithdrawal, uint _LUSDChange, bool _isDebtIncrease, address _upperHint, address _lowerHint, uint _maxFeePercentage) internal {
L282vars.LUSDFee = _triggerBorrowingFee(contractsCache.troveManager, contractsCache.lusdToken, _LUSDChange, _maxFeePercentage);
L312(vars.newColl, vars.newDebt) = _updateTroveFromAdjustment(contractsCache.troveManager, _borrower, _collateral, vars.collChange, vars.isCollIncrease, vars.netDebtChange, _isDebtIncrease);
L343function _triggerBorrowingFee(ITroveManager _troveManager, ILUSDToken _lusdToken, uint _LUSDAmount, uint _maxFeePercentage) internal returns (uint) {
L419function _withdrawLUSD(IActivePool _activePool, ILUSDToken _lusdToken, address _collateral, address _account, uint _LUSDAmount, uint _netDebtIncrease) internal {
L511function _repayLUSD(IActivePool _activePool, ILUSDToken _lusdToken, address _collateral, address _account, uint _LUSD) internal {
L517function _requireSufficientCollateralBalanceAndAllowance(address _user, address _collateral, uint _collAmount) internal view {
L528require(IERC20(_collateral).balanceOf(_user) >= _collAmount, "BorrowerOperations: Insufficient user collateral balance");
L529require(IERC20(_collateral).allowance(_user, address(this)) >= _collAmount, "BorrowerOperations: Insufficient collateral allowance");
L530function _requireTroveisNotActive(ITroveManager _troveManager, address _borrower, address _collateral) internal view {
L546require(_debtRepayment <= _currentDebt.sub(LUSD_GAS_COMPENSATION), "BorrowerOps: Amount repaid must not be larger than the Trove's debt");
L637function _requireSufficientLUSDBalance(ILUSDToken _lusdToken, address _borrower, uint _debtRepayment) internal view {
L644require(_lusdToken.balanceOf(_borrower) >= _debtRepayment, "BorrowerOps: Caller doesnt have enough LUSD to make repayment");
L645(uint newColl, uint newDebt) = _getNewTroveAmounts(_coll, _debt, _collChange, _isCollIncrease, _debtChange, _isDebtIncrease);
L675(uint newColl, uint newDebt) = _getNewTroveAmounts(_coll, _debt, _collChange, _isCollIncrease, _debtChange, _isDebtIncrease);
L697mapping (address => uint256) public yieldClaimThreshold; // collateral => minimum wei amount of yield to claim and redistribute
L47function setYieldDistributionParams(uint256 _treasurySplit, uint256 _SPSplit, uint256 _stakingSplit) external onlyOwner {
L144vars.percentOfFinalBal = vars.finalBalance == 0 ? uint256(-1) : vars.currentAllocated.mul(10_000).div(vars.finalBalance);
L258if (vars.percentOfFinalBal > vars.yieldingPercentage && vars.percentOfFinalBal.sub(vars.yieldingPercentage) > yieldingPercentageDrift) {
L264} else if(vars.percentOfFinalBal < vars.yieldingPercentage && vars.yieldingPercentage.sub(vars.percentOfFinalBal) > yieldingPercentageDrift) {
L269IERC4626(yieldGenerator[_collateral]).withdraw(uint256(-vars.netAssetMovement), address(this), address(this));
L282// profit is ultimately (coll at hand) + (coll allocated to yield generator) - (recorded total coll Amount in pool)
L287vars.profit = IERC20(_collateral).balanceOf(address(this)).add(vars.yieldingAmount).sub(collAmount[_collateral]);
L288uint LUSDLossPerUnitStaked) = _computeRewardsPerUnitStaked(_collateral, _collToAdd, _debtToOffset, totalLUSD);
L474function _updateRewardSumAndProduct(address _collateral, uint _collGainPerUnitStaked, uint _LUSDLossPerUnitStaked) internal {
L547function getDepositorCollateralGain(address _depositor) public view override returns (address[] memory assets, uint[] memory amounts) {
L626function _getCollateralGainFromSnapshots(uint initialDeposit, Snapshots storage snapshots) internal view returns (address[] memory assets, uint[] memory amounts) {
L637function _getSingularCollateralGain(uint _initialDeposit, address _collateral, Snapshots storage _snapshots) internal view returns (uint) {
L657vars.secondPortion = epochToScaleToSum[vars.epochSnapshot][vars.scaleSnapshot.add(1)][_collateral].div(SCALE_FACTOR);
L671vars.gain = _initialDeposit.mul(vars.firstPortion.add(vars.secondPortion)).div(vars.P_Snapshot).div(DECIMAL_PRECISION);
L673function _getPendingCollateralGain(address _user) internal view returns (address[] memory assets, uint[] memory amounts) {
L203shares = previewWithdraw(assets); // previewWithdraw() rounds up so exactly "assets" are withdrawn and not 1 wei less
L207Description:
Maximum suggested line length is 120 characters.
#0 - c4-judge
2023-03-10T10:36:16Z
trust1995 marked the issue as grade-b
#1 - c4-sponsor
2023-03-28T21:35:41Z
0xBebis marked the issue as sponsor confirmed