Platform: Code4rena
Start Date: 14/10/2022
Pot Size: $100,000 USDC
Total HM: 12
Participants: 75
Period: 9 days
Judge: GalloDaSballo
Total Solo HM: 1
Id: 171
League: ETH
Rank: 7/75
Findings: 4
Award: $4,521.14
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: KIntern_NA
4170.8571 USDC - $4,170.86
The '_setFeesParameters' function of LBPair.sol is not properly implemented, the static and dynamic fee parameters are overlapped due to missing of 114 bits shift for dynamic parameters. It will messes up the parameters and make the LBPair contract unavailable。
VS Code
function _setFeesParameters(bytes32 _packedFeeParameters) internal { // ... assembly { sstore(_feeParameters.slot, or(_newFeeParameters, shl(_OFFSET_VARIABLE_FEE_PARAMETERS, _varParameters))) } }
#0 - trust1995
2022-10-23T21:41:06Z
Dup of #425
#1 - GalloDaSballo
2022-10-25T23:21:06Z
Definitely would have liked to see a quick coded POC here
#2 - GalloDaSballo
2022-10-26T16:42:10Z
#3 - c4-judge
2022-11-23T18:31:09Z
GalloDaSballo marked the issue as not a duplicate
#4 - c4-judge
2022-11-23T18:31:53Z
GalloDaSballo marked the issue as duplicate of #384
#5 - Simon-Busch
2022-12-05T06:46:52Z
Marked this issue as satisfactory as requested by @GalloDaSballo
0.9728 USDC - $0.97
The '_burn' function of LBToken.sol call internal virtual function '_beforeTokenTransfer' with wrong order for parameter 'from' and 'to'. It causes the implementation of '_beforeTokenTransfer' in LBPaire.sol to update user's debt incorrectly, cause the system corrupted.
function _burn( address _account, uint256 _id, uint256 _amount ) internal virtual { // ... _beforeTokenTransfer(_account, address(0), _id, _amount); // ... }
#0 - trust1995
2022-10-23T22:09:30Z
Dup of #179
#1 - GalloDaSballo
2022-10-26T18:18:29Z
#2 - c4-judge
2022-11-11T21:22:53Z
GalloDaSballo changed the severity to 2 (Med Risk)
#3 - c4-judge
2022-11-11T21:22:57Z
GalloDaSballo marked the issue as satisfactory
#4 - c4-judge
2022-11-16T21:55:53Z
GalloDaSballo marked the issue as not a duplicate
#5 - c4-judge
2022-11-16T21:56:16Z
GalloDaSballo marked the issue as duplicate of #108
69.4984 USDC - $69.50
The implementation of 'flashLoan' in LBPair.sol allow users to loan as much as up to all funds in pair, but loan fees are credited to the active bin only, there is a chance a little reserve in the active bin getting unreasonably high ROI. It's recommended to distribute fees to both active bin and these adjacent ones based on their reserves. This way we incentivize liquidity providers to actively manage liquidity while ensuring fairness.
Manually review - VS code
Adding new internal function '_distributeLoanFee' and fix 'flashLoan' as follow:
function _distributeLoanFee( uint24 _id, FeeHelper.FeeParameters memory _fp, FeeHelper.FeesDistribution memory _fees, uint256 _amountOut, bool _loanForY ) internal { uint256 _left = _amountOut; while (_left != 0) { uint256 _reserve = _loanForY ? _bins[_id].reserveY : _bins[_id].reserveX; if (_reserve == 0) { _id = _tree.findFirstBin(_id, _loanForY); continue; } uint256 _amount; if (_left <= _reserve) { _amount = _left; _left = 0; } else { _amount = _reserve; unchecked { _left -= _reserve; } } FeeHelper.FeesDistribution memory _feesBin = _fp.getFeeAmountDistribution(_amount * _fees.total / _amountOut); if (_loanForY) { _bins[_id].accTokenYPerShare += _feesBin.getTokenPerShare(totalSupply(_id)); } else { _bins[_id].accTokenXPerShare += _feesBin.getTokenPerShare(totalSupply(_id)); } if (_left != 0) { _id = _tree.findFirstBin(_id, _loanForY); } } } function flashLoan( address _to, uint256 _amountXOut, uint256 _amountYOut, bytes calldata _data ) external override nonReentrant { (uint256 _reserveX, uint256 _reserveY, uint256 _id) = _getReservesAndId(); if (_amountXOut > _reserveX) revert LBPair__InsufficientReserveX(); if (_amountYOut > _reserveY) revert LBPair__InsufficientReserveY(); uint256 _fee = factory.flashLoanFee(); FeeHelper.FeeParameters memory _fp = _feeParameters; FeeHelper.FeesDistribution memory _feesX; FeeHelper.FeesDistribution memory _feesY; if (_amountXOut != 0) { // gas saving, since it's common to loan only one of the pair _feesX = _fp.getFeeAmountDistribution(_getFlashLoanFee(_amountXOut, _fee)); tokenX.safeTransfer(_to, _amountXOut); } if (_amountYOut != 0) { _feesY = _fp.getFeeAmountDistribution(_getFlashLoanFee(_amountYOut, _fee)); tokenY.safeTransfer(_to, _amountYOut); } ILBFlashLoanCallback(_to).LBFlashLoanCallback( msg.sender, _amountXOut, _amountYOut, _feesX.total, _feesY.total, _data ); if (_amountXOut != 0) { _feesX.flashLoanHelper(_pairInformation.feesX, tokenX, _reserveX); _distributeLoanFee(_id, _fp, _feesX, _amountXOut, false); } if (_amountYOut != 0) { _feesY.flashLoanHelper(_pairInformation.feesY, tokenY, _reserveY); _distributeLoanFee(_id, _fp, _feesY, _amountYOut, true); } emit FlashLoan(msg.sender, _to, _amountXOut, _amountYOut, _feesX.total, _feesY.total); }
#0 - trust1995
2022-10-23T22:03:19Z
Dup of #302
#1 - Shungy
2022-10-23T22:52:54Z
I believe this finding to be valid.
However, I think this report is of informational severity. Because the report have not identified an attack vector unlike the other reports mentioning the potential of value leak out of the protocol by way of stealing fees. Such as my report: https://github.com/code-423n4/2022-10-traderjoe-findings/issues/136. Additionally, the suggested fix is insufficient.
Disclaimer: Reduction of severity of this report would benefit me.
#2 - GalloDaSballo
2022-10-26T17:02:50Z
#3 - c4-judge
2022-11-13T17:19:55Z
GalloDaSballo marked the issue as satisfactory
#4 - c4-judge
2022-11-16T21:55:35Z
GalloDaSballo marked the issue as not a duplicate
#5 - c4-judge
2022-11-16T21:55:41Z
GalloDaSballo marked the issue as duplicate of #136
279.8109 USDC - $279.81
function findFirstBin( mapping(uint256 => uint256)[3] storage _tree, uint24 _binId, bool _rightSide ) internal view returns (uint24) { unchecked { uint256 current; uint256 bit; (_binId, bit) = _getIdsFromAbove(_binId); // Search in depth 2 if ((_rightSide && bit != 0) || (!_rightSide && bit != 255)) { current = _tree[2][_binId]; bit = current.closestBit(uint8(bit), _rightSide); if (bit != type(uint256).max) { return _getBottomId(_binId, uint24(bit)); } } (_binId, bit) = _getIdsFromAbove(_binId); // Search in depth 1 if ((_rightSide && bit != 0) || (!_rightSide && bit != 255)) { current = _tree[1][_binId]; bit = current.closestBit(uint8(bit), _rightSide); if (bit != type(uint256).max) { _binId = _getBottomId(_binId, uint24(bit)); current = _tree[2][_binId]; return _getBottomId(_binId, current.significantBit(_rightSide)); } } // @audit missing check here // Search in depth 0 current = _tree[0][0]; bit = current.closestBit(uint8(_binId), _rightSide); if (bit == type(uint256).max) revert TreeMath__ErrorDepthSearch(); current = _tree[1][bit]; _binId = _getBottomId(uint24(bit), current.significantBit(_rightSide)); current = _tree[2][_binId]; return _getBottomId(_binId, current.significantBit(_rightSide)); } }
#0 - GalloDaSballo
2022-11-09T20:08:09Z
R
#1 - GalloDaSballo
2022-11-09T20:08:12Z
1R
#2 - c4-judge
2022-11-16T21:08:33Z
GalloDaSballo marked the issue as grade-b