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: 19/75
Findings: 1
Award: $613.77
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: shung
Also found by: 0x4non, IllIllI, LeoS, Mathieu, MiloTruck, ReyAdmirado, Saintcode_, Shishigami, TomJ, __141345__, c3phas, m_Rassska, pfapostol
613.7687 USDC - $613.77
Gas savings are estimated using the gas report of existing forge test --gas-report
tests (the sum of all deployment costs and the sum of the costs of calling methods) and may vary depending on the implementation of the fix.
Issue | Instances | Estimated gas(deployments) | Estimated gas(min method call) | Estimated gas(avg method call) | Estimated gas(max method call) | |
---|---|---|---|---|---|---|
1 | Use functions instead of modifiers | 8 | 1 065 143 | -974 | -1 557 | -2 027 |
2 | Use a more recent version of solidity | 37 | 821 258 | 4 612 | 16 393 | 37 384 |
3 | Duplicated require()/revert() checks should be refactored to a modifier or function | 38 | 566 224 | -424 | -1 473 | -2 818 |
4 | Unchecking arithmetics operations that can't underflow/overflow | 2 | 58 524 | 0 | 651 | 1 104 |
5 | Use of the memory keyword when storage pointer should be used | 4 | 53 523 | 55 | 13 580 | 15 945 |
6 | Using calldata instead of memory for read-only arguments in external functions saves gas | 1 | 39 086 | 2 256 | 1 199 | -2 165 |
7 | Do not cache msg.sender | 1 | 13 843 | 0 | -140 | 35 |
8 | Unnecessary else statement | 4 | 7 217 | 0 | -88 | 338 |
9 | ++i costs less gas than i++ , especially when it's used in for-loops (--i /i-- too) | 5 | 2 800 | 0 | 32 | 69 |
Overall Gas Saving | 100 | 2 623 283 | 5 381 | 28 755 | 48 090 |
Total: 100 instances over 9 issues
Deployment. Gas Saved: 1 065 143
Minimum Method Call. Gas Saved: -974
Average Method Call. Gas Saved: -1 557
Maximum Method Call. Gas Saved: -2 027
Overall gas change: -477 008 (-0.302%)
diff --git a/src/LBPair.sol b/src/LBPair.sol index 717270e..edb50ac 100644 --- a/src/LBPair.sol +++ b/src/LBPair.sol @@ -40,9 +40,8 @@ contract LBPair is LBToken, ReentrancyGuardUpgradeable, ILBPair { 40, 40: 41, 41: /** Modifiers **/ 42, 42: - 43 :- modifier onlyFactory() { + 43:+ function onlyFactory() private { 44, 44: if (msg.sender != address(factory)) revert LBPair__OnlyFactory(); - 45 :- _; 46, 45: } 47, 46: 48, 47: /** Public immutable variables **/ @@ -107,7 +106,8 @@ contract LBPair is LBToken, ReentrancyGuardUpgradeable, ILBPair { 107, 106: uint24 _activeId, 108, 107: uint16 _sampleLifetime, 109, 108: bytes32 _packedFeeParameters - 110 :- ) external override onlyFactory { + 109:+ ) external override { + 110:+ onlyFactory(); 111, 111: if (address(_tokenX) == address(0) || address(_tokenY) == address(0)) revert LBPair__AddressZero(); 112, 112: if (address(tokenX) != address(0)) revert LBPair__AlreadyInitialized(); 113, 113: @@ -785,11 +785,13 @@ contract LBPair is LBToken, ReentrancyGuardUpgradeable, ILBPair { 785, 785: /// The bin step will not change 786, 786: /// Only callable by the factory 787, 787: /// @param _packedFeeParameters The packed fee parameters - 788 :- function setFeesParameters(bytes32 _packedFeeParameters) external override onlyFactory { + 788:+ function setFeesParameters(bytes32 _packedFeeParameters) external override { + 789:+ onlyFactory(); 789, 790: _setFeesParameters(_packedFeeParameters); 790, 791: } 791, 792: - 792 :- function forceDecay() external override onlyFactory { + 793:+ function forceDecay() external override { + 794:+ onlyFactory(); 793, 795: unchecked { 794, 796: _feeParameters.volatilityReference = uint24( 795, 797: (uint256(_feeParameters.reductionFactor) * _feeParameters.volatilityReference) /
diff --git a/src/LBRouter.sol b/src/LBRouter.sol index 567c49a..2cf7514 100644 --- a/src/LBRouter.sol +++ b/src/LBRouter.sol @@ -29,9 +29,8 @@ contract LBRouter is ILBRouter { 29, 29: IJoeFactory public immutable override oldFactory; 30, 30: IWAVAX public immutable override wavax; 31, 31: - 32 :- modifier onlyFactoryOwner() { + 32:+ function onlyFactoryOwner() private { 33, 33: if (msg.sender != factory.owner()) revert LBRouter__NotFactoryOwner(); - 34 :- _; 35, 34: } 36, 35: 37, 36: modifier ensure(uint256 _deadline) { @@ -623,7 +622,8 @@ contract LBRouter is ILBRouter { 623, 622: IERC20 _token, 624, 623: address _to, 625, 624: uint256 _amount - 626 :- ) external override onlyFactoryOwner { + 625:+ ) external override { + 626:+ onlyFactoryOwner(); 627, 627: if (address(_token) == address(0)) { 628, 628: if (_amount == type(uint256).max) _amount = address(this).balance; 629, 629: _safeTransferAVAX(_to, _amount); @@ -644,7 +644,8 @@ contract LBRouter is ILBRouter { 644, 644: address _to, 645, 645: uint256[] memory _ids, 646, 646: uint256[] memory _amounts - 647 :- ) external override onlyFactoryOwner { + 647:+ ) external override { + 648:+ onlyFactoryOwner(); 648, 649: _lbToken.safeBatchTransferFrom(address(this), _to, _ids, _amounts); 649, 650: } 650, 651:
diff --git a/src/LBRouter.sol b/src/LBRouter.sol index 2cf7514..200c7e2 100644 --- a/src/LBRouter.sol +++ b/src/LBRouter.sol @@ -33,15 +33,13 @@ contract LBRouter is ILBRouter { 33, 33: if (msg.sender != factory.owner()) revert LBRouter__NotFactoryOwner(); 34, 34: } 35, 35: - 36 :- modifier ensure(uint256 _deadline) { + 36:+ function ensure(uint256 _deadline) private { 37, 37: if (block.timestamp > _deadline) revert LBRouter__DeadlineExceeded(_deadline, block.timestamp); - 38 :- _; 39, 38: } 40, 39: - 41 :- modifier verifyInputs(uint256[] memory _pairBinSteps, IERC20[] memory _tokenPath) { + 40:+ function verifyInputs(uint256[] memory _pairBinSteps, IERC20[] memory _tokenPath) private { 42, 41: if (_pairBinSteps.length == 0 || _pairBinSteps.length + 1 != _tokenPath.length) 43, 42: revert LBRouter__LengthsMismatch(); - 44 :- _; 45, 43: } 46, 44: 47, 45: /// @notice Constructor @@ -280,7 +278,8 @@ contract LBRouter is ILBRouter { 280, 278: uint256[] memory _amounts, 281, 279: address _to, 282, 280: uint256 _deadline - 283 :- ) external override ensure(_deadline) returns (uint256 amountX, uint256 amountY) { + 281:+ ) external override returns (uint256 amountX, uint256 amountY) { + 282:+ ensure(_deadline); 284, 283: ILBPair _LBPair = _getLBPairInformation(_tokenX, _tokenY, _binStep); 285, 284: if (_tokenX != _LBPair.tokenX()) { 286, 285: (_tokenX, _tokenY) = (_tokenY, _tokenX); @@ -313,7 +312,8 @@ contract LBRouter is ILBRouter { 313, 312: uint256[] memory _amounts, 314, 313: address payable _to, 315, 314: uint256 _deadline - 316 :- ) external override ensure(_deadline) returns (uint256 amountToken, uint256 amountAVAX) { + 315:+ ) external override returns (uint256 amountToken, uint256 amountAVAX) { + 316:+ ensure(_deadline); 317, 317: ILBPair _LBPair = _getLBPairInformation(_token, IERC20(wavax), _binStep); 318, 318: 319, 319: bool _isAVAXTokenY = IERC20(wavax) == _LBPair.tokenY(); @@ -355,7 +355,9 @@ contract LBRouter is ILBRouter { 355, 355: IERC20[] memory _tokenPath, 356, 356: address _to, 357, 357: uint256 _deadline - 358 :- ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { + 358:+ ) external override returns (uint256 amountOut) { + 359:+ ensure(_deadline); + 360:+ verifyInputs(_pairBinSteps, _tokenPath); 359, 361: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 360, 362: 361, 363: _tokenPath[0].safeTransferFrom(msg.sender, _pairs[0], _amountIn); @@ -380,7 +382,9 @@ contract LBRouter is ILBRouter { 380, 382: IERC20[] memory _tokenPath, 381, 383: address payable _to, 382, 384: uint256 _deadline - 383 :- ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { + 385:+ ) external override returns (uint256 amountOut) { + 386:+ ensure(_deadline); + 387:+ verifyInputs(_pairBinSteps, _tokenPath); 384, 388: if (_tokenPath[_pairBinSteps.length] != IERC20(wavax)) 385, 389: revert LBRouter__InvalidTokenPath(address(_tokenPath[_pairBinSteps.length])); 386, 390: @@ -409,7 +413,9 @@ contract LBRouter is ILBRouter { 409, 413: IERC20[] memory _tokenPath, 410, 414: address _to, 411, 415: uint256 _deadline - 412 :- ) external payable override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { + 416:+ ) external payable override returns (uint256 amountOut) { + 417:+ ensure(_deadline); + 418:+ verifyInputs(_pairBinSteps, _tokenPath); 413, 419: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 414, 420: 415, 421: _wavaxDepositAndTransfer(_pairs[0], msg.value); @@ -434,7 +440,9 @@ contract LBRouter is ILBRouter { 434, 440: IERC20[] memory _tokenPath, 435, 441: address _to, 436, 442: uint256 _deadline - 437 :- ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256[] memory amountsIn) { + 443:+ ) external override returns (uint256[] memory amountsIn) { + 444:+ ensure(_deadline); + 445:+ verifyInputs(_pairBinSteps, _tokenPath); 438, 446: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 439, 447: amountsIn = _getAmountsIn(_pairBinSteps, _pairs, _tokenPath, _amountOut); 440, 448: @@ -462,7 +470,9 @@ contract LBRouter is ILBRouter { 462, 470: IERC20[] memory _tokenPath, 463, 471: address payable _to, 464, 472: uint256 _deadline - 465 :- ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256[] memory amountsIn) { + 473:+ ) external override returns (uint256[] memory amountsIn) { + 474:+ ensure(_deadline); + 475:+ verifyInputs(_pairBinSteps, _tokenPath); 466, 476: if (_tokenPath[_pairBinSteps.length] != IERC20(wavax)) 467, 477: revert LBRouter__InvalidTokenPath(address(_tokenPath[_pairBinSteps.length])); 468, 478: @@ -499,10 +509,10 @@ contract LBRouter is ILBRouter { 499, 509: external 500, 510: payable 501, 511: override - 502 :- ensure(_deadline) - 503 :- verifyInputs(_pairBinSteps, _tokenPath) 504, 512: returns (uint256[] memory amountsIn) 505, 513: { + 514:+ ensure(_deadline); + 515:+ verifyInputs(_pairBinSteps, _tokenPath); 506, 516: if (_tokenPath[0] != IERC20(wavax)) revert LBRouter__InvalidTokenPath(address(_tokenPath[0])); 507, 517: 508, 518: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); @@ -534,7 +544,9 @@ contract LBRouter is ILBRouter { 534, 544: IERC20[] memory _tokenPath, 535, 545: address _to, 536, 546: uint256 _deadline - 537 :- ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { + 547:+ ) external override returns (uint256 amountOut) { + 548:+ ensure(_deadline); + 549:+ verifyInputs(_pairBinSteps, _tokenPath); 538, 550: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 539, 551: 540, 552: IERC20 _targetToken = _tokenPath[_pairs.length]; @@ -564,7 +576,9 @@ contract LBRouter is ILBRouter { 564, 576: IERC20[] memory _tokenPath, 565, 577: address payable _to, 566, 578: uint256 _deadline - 567 :- ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { + 579:+ ) external override returns (uint256 amountOut) { + 580:+ ensure(_deadline); + 581:+ verifyInputs(_pairBinSteps, _tokenPath); 568, 582: if (_tokenPath[_pairBinSteps.length] != IERC20(wavax)) 569, 583: revert LBRouter__InvalidTokenPath(address(_tokenPath[_pairBinSteps.length])); 570, 584: @@ -596,7 +610,9 @@ contract LBRouter is ILBRouter { 596, 610: IERC20[] memory _tokenPath, 597, 611: address _to, 598, 612: uint256 _deadline - 599 :- ) external payable override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { + 613:+ ) external payable override returns (uint256 amountOut) { + 614:+ ensure(_deadline); + 615:+ verifyInputs(_pairBinSteps, _tokenPath); 600, 616: if (_tokenPath[0] != IERC20(wavax)) revert LBRouter__InvalidTokenPath(address(_tokenPath[0])); 601, 617: 602, 618: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); @@ -656,9 +672,10 @@ contract LBRouter is ILBRouter { 656, 672: /// @return liquidityMinted Amounts of LBToken minted for each bin 657, 673: function _addLiquidity(LiquidityParameters memory _liq, ILBPair _LBPair) 658, 674: private - 659 :- ensure(_liq.deadline) + 675:+ 660, 676: returns (uint256[] memory depositIds, uint256[] memory liquidityMinted) 661, 677: { + 678:+ ensure(_liq.deadline); 662, 679: unchecked { 663, 680: if (_liq.deltaIds.length != _liq.distributionX.length && _liq.deltaIds.length != _liq.distributionY.length) 664, 681: revert LBRouter__LengthsMismatch();
diff --git a/src/LBToken.sol b/src/LBToken.sol index 47aa528..8a184be 100644 --- a/src/LBToken.sol +++ b/src/LBToken.sol @@ -29,19 +29,16 @@ contract LBToken is ILBToken { 29, 29: string private constant _name = "Liquidity Book Token"; 30, 30: string private constant _symbol = "LBT"; 31, 31: - 32 :- modifier checkApproval(address _from, address _spender) { + 32:+ function checkApproval(address _from, address _spender) private view { 33, 33: if (!_isApprovedForAll(_from, _spender)) revert LBToken__SpenderNotApproved(_from, _spender); - 34 :- _; 35, 34: } 36, 35: - 37 :- modifier checkAddresses(address _from, address _to) { + 36:+ function checkAddresses(address _from, address _to) private pure { 38, 37: if (_from == address(0) || _to == address(0)) revert LBToken__TransferFromOrToAddress0(); - 39 :- _; 40, 38: } 41, 39: - 42 :- modifier checkLength(uint256 _lengthA, uint256 _lengthB) { + 40:+ function checkLength(uint256 _lengthA, uint256 _lengthB) private pure { 43, 41: if (_lengthA != _lengthB) revert LBToken__LengthMismatch(_lengthA, _lengthB); - 44 :- _; 45, 42: } 46, 43: 47, 44: /// @notice Returns the name of the token @@ -81,9 +78,9 @@ contract LBToken is ILBToken { 81, 78: view 82, 79: virtual 83, 80: override - 84 :- checkLength(_accounts.length, _ids.length) 85, 81: returns (uint256[] memory batchBalances) 86, 82: { + 83:+ checkLength(_accounts.length, _ids.length); 87, 84: batchBalances = new uint256[](_accounts.length); 88, 85: 89, 86: unchecked { @@ -133,7 +130,9 @@ contract LBToken is ILBToken { 133, 130: address _to, 134, 131: uint256 _id, 135, 132: uint256 _amount - 136 :- ) public virtual override checkAddresses(_from, _to) checkApproval(_from, msg.sender) { + 133:+ ) public virtual override { + 134:+ checkAddresses(_from, _to); + 135:+ checkApproval(_from, msg.sender); 137, 136: address _spender = msg.sender; 138, 137: 139, 138: _transfer(_from, _to, _id, _amount); @@ -154,11 +153,11 @@ contract LBToken is ILBToken { 154, 153: ) 155, 154: public 156, 155: virtual - 157 :- override - 158 :- checkLength(_ids.length, _amounts.length) - 159 :- checkAddresses(_from, _to) - 160 :- checkApproval(_from, msg.sender) + 156:+ override 161, 157: { + 158:+ checkLength(_ids.length, _amounts.length); + 159:+ checkAddresses(_from, _to); + 160:+ checkApproval(_from, msg.sender); 162, 161: unchecked { 163, 162: for (uint256 i; i < _ids.length; ++i) { 164, 163: _transfer(_from, _to, _ids[i], _amounts[i]);
diff --git a/src/LBFactory.sol b/src/LBFactory.sol index 32ee39c..6b6a58f 100644 --- a/src/LBFactory.sol +++ b/src/LBFactory.sol @@ -212,7 +212,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 212, 212: /// @notice Set the LBPair implementation address 213, 213: /// @dev Needs to be called by the owner 214, 214: /// @param _LBPairImplementation The address of the implementation - 215 :- function setLBPairImplementation(address _LBPairImplementation) external override onlyOwner { + 215:+ function setLBPairImplementation(address _LBPairImplementation) external override { + 216:+ onlyOwner(); 216, 217: if (ILBPair(_LBPairImplementation).factory() != this) 217, 218: revert LBFactory__LBPairSafetyCheckFailed(_LBPairImplementation); 218, 219: @@ -314,7 +315,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 314, 315: IERC20 _tokenY, 315, 316: uint256 _binStep, 316, 317: bool _ignored - 317 :- ) external override onlyOwner { + 318:+ ) external override { + 319:+ onlyOwner(); 318, 320: (IERC20 _tokenA, IERC20 _tokenB) = _sortTokens(_tokenX, _tokenY); 319, 321: 320, 322: LBPairInformation memory _LBPairInformation = _LBPairsInfo[_tokenA][_tokenB][_binStep]; @@ -347,7 +349,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 347, 349: uint16 _protocolShare, 348, 350: uint24 _maxVolatilityAccumulated, 349, 351: uint16 _sampleLifetime - 350 :- ) external override onlyOwner { + 352:+ ) external override { + 353:+ onlyOwner(); 351, 354: bytes32 _packedFeeParameters = _getPackedFeeParameters( 352, 355: _binStep, 353, 356: _baseFactor, @@ -393,7 +396,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 393, 396: 394, 397: /// @notice Remove the preset linked to a binStep 395, 398: /// @param _binStep The bin step to remove - 396 :- function removePreset(uint16 _binStep) external override onlyOwner { + 399:+ function removePreset(uint16 _binStep) external override { + 400:+ onlyOwner(); 397, 401: if (_presets[_binStep] == bytes32(0)) revert LBFactory__BinStepHasNoPreset(_binStep); 398, 402: 399, 403: // Set the bit `_binStep` to 0 @@ -431,7 +435,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 431, 435: uint24 _variableFeeControl, 432, 436: uint16 _protocolShare, 433, 437: uint24 _maxVolatilityAccumulated - 434 :- ) external override onlyOwner { + 438:+ ) external override { + 439:+ onlyOwner(); 435, 440: ILBPair _LBPair = _getLBPairInformation(_tokenX, _tokenY, _binStep).LBPair; 436, 441: 437, 442: if (address(_LBPair) == address(0)) revert LBFactory__LBPairNotCreated(_tokenX, _tokenY, _binStep); @@ -465,13 +470,15 @@ contract LBFactory is PendingOwnable, ILBFactory { 465, 470: 466, 471: /// @notice Function to set the recipient of the fees. This address needs to be able to receive ERC20s 467, 472: /// @param _feeRecipient The address of the recipient - 468 :- function setFeeRecipient(address _feeRecipient) external override onlyOwner { + 473:+ function setFeeRecipient(address _feeRecipient) external override { + 474:+ onlyOwner(); 469, 475: _setFeeRecipient(_feeRecipient); 470, 476: } 471, 477: 472, 478: /// @notice Function to set the flash loan fee 473, 479: /// @param _flashLoanFee The value of the fee for flash loan - 474 :- function setFlashLoanFee(uint256 _flashLoanFee) external override onlyOwner { + 480:+ function setFlashLoanFee(uint256 _flashLoanFee) external override { + 481:+ onlyOwner(); 475, 482: uint256 _oldFlashLoanFee = flashLoanFee; 476, 483: 477, 484: if (_oldFlashLoanFee == _flashLoanFee) revert LBFactory__SameFlashLoanFee(_flashLoanFee); @@ -482,7 +489,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 482, 489: 483, 490: /// @notice Function to set the creation restriction of the Factory 484, 491: /// @param _locked If the creation is restricted (true) or not (false) - 485 :- function setFactoryLockedState(bool _locked) external override onlyOwner { + 492:+ function setFactoryLockedState(bool _locked) external override { + 493:+ onlyOwner(); 486, 494: if (creationUnlocked != _locked) revert LBFactory__FactoryLockIsAlreadyInTheSameState(); 487, 495: creationUnlocked = !_locked; 488, 496: emit FactoryLockedStatusUpdated(_locked); @@ -490,7 +498,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 490, 498: 491, 499: /// @notice Function to add an asset to the whitelist of quote assets 492, 500: /// @param _quoteAsset The quote asset (e.g: AVAX, USDC...) - 493 :- function addQuoteAsset(IERC20 _quoteAsset) external override onlyOwner { + 501:+ function addQuoteAsset(IERC20 _quoteAsset) external override { + 502:+ onlyOwner(); 494, 503: if (!_quoteAssetWhitelist.add(address(_quoteAsset))) 495, 504: revert LBFactory__QuoteAssetAlreadyWhitelisted(_quoteAsset); 496, 505: @@ -499,7 +508,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 499, 508: 500, 509: /// @notice Function to remove an asset to the whitelist of quote assets 501, 510: /// @param _quoteAsset The quote asset (e.g: AVAX, USDC...) - 502 :- function removeQuoteAsset(IERC20 _quoteAsset) external override onlyOwner { + 511:+ function removeQuoteAsset(IERC20 _quoteAsset) external override { + 512:+ onlyOwner(); 503, 513: if (!_quoteAssetWhitelist.remove(address(_quoteAsset))) revert LBFactory__QuoteAssetNotWhitelisted(_quoteAsset); 504, 514: 505, 515: emit QuoteAssetRemoved(_quoteAsset); @@ -517,7 +527,8 @@ contract LBFactory is PendingOwnable, ILBFactory { 517, 527: emit FeeRecipientSet(_oldFeeRecipient, _feeRecipient); 518, 528: } 519, 529: - 520 :- function forceDecay(ILBPair _LBPair) external override onlyOwner { + 530:+ function forceDecay(ILBPair _LBPair) external override { + 531:+ onlyOwner(); 521, 532: _LBPair.forceDecay(); 522, 533: } 523, 534:
diff --git a/src/libraries/PendingOwnable.sol b/src/libraries/PendingOwnable.sol index f745362..bb29ec8 100644 --- a/src/libraries/PendingOwnable.sol +++ b/src/libraries/PendingOwnable.sol @@ -26,9 +26,8 @@ contract PendingOwnable is IPendingOwnable { 26, 26: address private _pendingOwner; 27, 27: 28, 28: /// @notice Throws if called by any account other than the owner. - 29 :- modifier onlyOwner() { + 29:+ function onlyOwner() internal view { 30, 30: if (msg.sender != _owner) revert PendingOwnable__NotOwner(); - 31 :- _; 32, 31: } 33, 32: 34, 33: /// @notice Throws if called by any account other than the pending owner. @@ -56,7 +55,8 @@ contract PendingOwnable is IPendingOwnable { 56, 55: 57, 56: /// @notice Sets the pending owner address. This address will be able to become 58, 57: /// the owner of this contract by calling {becomeOwner} - 59 :- function setPendingOwner(address pendingOwner_) public override onlyOwner { + 58:+ function setPendingOwner(address pendingOwner_) public override { + 59:+ onlyOwner(); 60, 60: if (pendingOwner_ == address(0)) revert PendingOwnable__AddressZero(); 61, 61: if (_pendingOwner != address(0)) revert PendingOwnable__PendingOwnerAlreadySet(); 62, 62: _setPendingOwner(pendingOwner_); @@ -65,7 +65,8 @@ contract PendingOwnable is IPendingOwnable { 65, 65: /// @notice Revoke the pending owner address. This address will not be able to 66, 66: /// call {becomeOwner} to become the owner anymore. 67, 67: /// Can only be called by the owner - 68 :- function revokePendingOwner() public override onlyOwner { + 68:+ function revokePendingOwner() public override { + 69:+ onlyOwner(); 69, 70: if (_pendingOwner == address(0)) revert PendingOwnable__NoPendingOwner(); 70, 71: _setPendingOwner(address(0)); 71, 72: } @@ -81,7 +82,8 @@ contract PendingOwnable is IPendingOwnable { 81, 82: /// 82, 83: /// NOTE: Renouncing ownership will leave the contract without an owner, 83, 84: /// thereby removing any functionality that is only available to the owner. - 84 :- function renounceOwnership() public override onlyOwner { + 85:+ function renounceOwnership() public override { + 86:+ onlyOwner(); 85, 87: _transferOwnership(address(0)); 86, 88: } 87, 89: diff --git a/test/mocks/Faucet.sol b/test/mocks/Faucet.sol index 108bde7..da1835f 100644 --- a/test/mocks/Faucet.sol +++ b/test/mocks/Faucet.sol @@ -93,14 +93,16 @@ contract Faucet is PendingOwnable { 93, 93: /// @dev Tokens need to be owned by the faucet, and only mintable by the owner 94, 94: /// @param _token The address of the token 95, 95: /// @param _amountPerRequest The amount per request - 96 :- function addFaucetToken(IERC20 _token, uint96 _amountPerRequest) external onlyOwner { + 96:+ function addFaucetToken(IERC20 _token, uint96 _amountPerRequest) external { + 97:+ onlyOwner(); 97, 98: _addFaucetToken(FaucetToken({ERC20: _token, amountPerRequest: _amountPerRequest})); 98, 99: } 99, 100: 100, 101: /// @notice Remove a token from the faucet 101, 102: /// @dev Token needs to be in the set, and AVAX can't be removed 102, 103: /// @param _token The address of the token - 103 :- function removeFaucetToken(IERC20 _token) external onlyOwner { + 104:+ function removeFaucetToken(IERC20 _token) external { + 105:+ onlyOwner(); 104, 106: uint256 index = tokenToIndices[_token]; 105, 107: 106, 108: require(index >= 2, "Not a faucet token"); @@ -115,7 +117,8 @@ contract Faucet is PendingOwnable { 115, 117: /// @notice Set the request cooldown for every users 116, 118: /// @dev This function needs to be called by the owner 117, 119: /// @param _requestCooldown The new cooldown - 118 :- function setRequestCooldown(uint256 _requestCooldown) external onlyOwner { + 120:+ function setRequestCooldown(uint256 _requestCooldown) external { + 121:+ onlyOwner(); 119, 122: _setRequestCooldown(_requestCooldown); 120, 123: } 121, 124: @@ -123,7 +126,8 @@ contract Faucet is PendingOwnable { 123, 126: /// @dev This function needs to be called by the owner 124, 127: /// @param _token The address of the token 125, 128: /// @param _amountPerRequest The new amount per request - 126 :- function setAmountPerRequest(IERC20 _token, uint96 _amountPerRequest) external onlyOwner { + 129:+ function setAmountPerRequest(IERC20 _token, uint96 _amountPerRequest) external { + 130:+ onlyOwner(); 127, 131: _setAmountPerRequest(_token, _amountPerRequest); 128, 132: } 129, 133: @@ -136,20 +140,23 @@ contract Faucet is PendingOwnable { 136, 140: IERC20 _token, 137, 141: address _to, 138, 142: uint256 _amount - 139 :- ) external onlyOwner { + 143:+ ) external { + 144:+ onlyOwner(); 140, 145: if (address(_token) == address(0)) _sendAvax(_to, _amount); 141, 146: else _token.safeTransfer(_to, _amount); 142, 147: } 143, 148: 144, 149: /// @notice Set the address of the operator 145, 150: /// @param _newOperator The address of the new operator - 146 :- function setOperator(address _newOperator) external onlyOwner { + 151:+ function setOperator(address _newOperator) external { + 152:+ onlyOwner(); 147, 153: operator = _newOperator; 148, 154: } 149, 155: 150, 156: /// @notice Set whether the direct request is unlocked or not 151, 157: /// @param _unlockedRequest The address of the new operator - 152 :- function setUnlockedRequest(bool _unlockedRequest) external onlyOwner { + 158:+ function setUnlockedRequest(bool _unlockedRequest) external { + 159:+ onlyOwner(); 153, 160: unlockedRequest = _unlockedRequest; 154, 161: } 155, 162:
Use a solidity version of at least 0.8.0 to get overflow protection without SafeMath Use a solidity version of at least 0.8.2 to get simple compiler automatic inlining Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require() strings Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value
NOTE: compared to 0.8.7 which the project uses by default
Deployment. Gas Saved: 821 258
Minimum Method Call. Gas Saved: 4 612
Average Method Call. Gas Saved: 16 393
Maximum Method Call. Gas Saved: 37 384
Overall gas change: -581 263 (-81.312%)
2022-10-traderjoe/src/interfaces/IJoeFactory.sol 2022-10-traderjoe/src/interfaces/IJoePair.sol 2022-10-traderjoe/src/interfaces/IJoeRouter01.sol 2022-10-traderjoe/src/interfaces/IJoeRouter02.sol 2022-10-traderjoe/src/interfaces/ILBFactory.sol 2022-10-traderjoe/src/interfaces/ILBFlashLoanCallback.sol 2022-10-traderjoe/src/interfaces/ILBPair.sol 2022-10-traderjoe/src/interfaces/ILBRouter.sol 2022-10-traderjoe/src/interfaces/ILBToken.sol 2022-10-traderjoe/src/interfaces/IPendingOwnable.sol 2022-10-traderjoe/src/interfaces/IWAVAX.sol 2022-10-traderjoe/src/libraries/BinHelper.sol 2022-10-traderjoe/src/libraries/BitMath.sol 2022-10-traderjoe/src/libraries/Buffer.sol 2022-10-traderjoe/src/libraries/Constants.sol 2022-10-traderjoe/src/libraries/Decoder.sol 2022-10-traderjoe/src/libraries/Encoder.sol 2022-10-traderjoe/src/libraries/FeeDistributionHelper.sol 2022-10-traderjoe/src/libraries/FeeHelper.sol 2022-10-traderjoe/src/libraries/JoeLibrary.sol 2022-10-traderjoe/src/libraries/Math128x128.sol 2022-10-traderjoe/src/libraries/Math512Bits.sol 2022-10-traderjoe/src/libraries/Oracle.sol 2022-10-traderjoe/src/libraries/PendingOwnable.sol 2022-10-traderjoe/src/libraries/ReentrancyGuardUpgradeable.sol 2022-10-traderjoe/src/libraries/SafeCast.sol 2022-10-traderjoe/src/libraries/SafeMath.sol 2022-10-traderjoe/src/libraries/Samples.sol 2022-10-traderjoe/src/libraries/SwapHelper.sol 2022-10-traderjoe/src/libraries/TokenHelper.sol 2022-10-traderjoe/src/libraries/TreeMath.sol 2022-10-traderjoe/src/LBErrors.sol 2022-10-traderjoe/src/LBFactory.sol 2022-10-traderjoe/src/LBPair.sol 2022-10-traderjoe/src/LBQuoter.sol 2022-10-traderjoe/src/LBRouter.sol 2022-10-traderjoe/src/LBToken.sol
3,1: pragma solidity ^0.8.0;
Deployment. Gas Saved: 566 224
Minimum Method Call. Gas Saved: -424
Average Method Call. Gas Saved: -1 473
Maximum Method Call. Gas Saved: -2 818
Overall gas change: -174 947 (-0.950%)
diff --git a/src/LBErrors.sol b/src/LBErrors.sol index 092ede5..d8e5ddd 100644 --- a/src/LBErrors.sol +++ b/src/LBErrors.sol @@ -4,6 +4,12 @@ pragma solidity ^0.8.0; 4, 4: 5, 5: import "./interfaces/ILBPair.sol"; 6, 6: + 7:+/** Common errors */ + 8:+ + 9:+error IdOverflows(int256 id); + 10:+error AddressZero(); + 11:+error InsufficientLiquidity(); + 12:+ 7, 13: /** LBRouter errors */ 8, 14: 9, 15: error LBRouter__SenderIsNotWAVAX(); @@ -14,7 +20,6 @@ error LBRouter__BrokenSwapSafetyCheck(); 14, 20: error LBRouter__NotFactoryOwner(); 15, 21: error LBRouter__TooMuchTokensIn(uint256 excess); 16, 22: error LBRouter__BinReserveOverflows(uint256 id); - 17 :-error LBRouter__IdOverflows(int256 id); 18, 23: error LBRouter__LengthsMismatch(); 19, 24: error LBRouter__WrongTokenOrder(); 20, 25: error LBRouter__IdSlippageCaught(uint256 activeIdDesired, uint256 idSlippage, uint256 activeId); @@ -51,7 +56,6 @@ error LBToken__TransferExceedsBalance(address from, uint256 id, uint256 amount); 51, 56: error LBFactory__IdenticalAddresses(IERC20 token); 52, 57: error LBFactory__QuoteAssetNotWhitelisted(IERC20 quoteAsset); 53, 58: error LBFactory__QuoteAssetAlreadyWhitelisted(IERC20 quoteAsset); - 54 :-error LBFactory__AddressZero(); 55, 59: error LBFactory__LBPairAlreadyExists(IERC20 tokenX, IERC20 tokenY, uint256 _binStep); 56, 60: error LBFactory__LBPairNotCreated(IERC20 tokenX, IERC20 tokenY, uint256 binStep); 57, 61: error LBFactory__DecreasingPeriods(uint16 filterPeriod, uint16 decayPeriod); @@ -75,7 +79,6 @@ error LBFactory__ImplementationNotSet(); 75, 79: /** LBPair errors */ 76, 80: 77, 81: error LBPair__InsufficientAmounts(); - 78 :-error LBPair__AddressZero(); 79, 82: error LBPair__BrokenSwapSafetyCheck(); 80, 83: error LBPair__CompositionFactorFlawed(uint256 id); 81, 84: error LBPair__InsufficientLiquidityMinted(uint256 id); @@ -93,7 +96,6 @@ error LBPair__NewSizeTooSmall(uint256 newSize, uint256 oracleSize); 93, 96: /** BinHelper errors */ 94, 97: 95, 98: error BinHelper__BinStepOverflows(uint256 bp); - 96 :-error BinHelper__IdOverflows(int256 id); 97, 99: error BinHelper__IntOverflows(uint256 id); 98, 100: 99, 101: /** FeeDistributionHelper errors */ @@ -124,7 +126,6 @@ error PendingOwnable__NotOwner(); 124, 126: error PendingOwnable__NotPendingOwner(); 125, 127: error PendingOwnable__PendingOwnerAlreadySet(); 126, 128: error PendingOwnable__NoPendingOwner(); - 127 :-error PendingOwnable__AddressZero(); 128, 129: 129, 130: /** ReentrancyGuardUpgradeable errors */ 130, 131: @@ -173,9 +174,7 @@ error TreeMath__ErrorDepthSearch(); 173, 174: /** JoeLibrary errors */ 174, 175: 175, 176: error JoeLibrary__IdenticalAddresses(); - 176 :-error JoeLibrary__AddressZero(); 177, 177: error JoeLibrary__InsufficientAmount(); - 178 :-error JoeLibrary__InsufficientLiquidity(); 179, 178: 180, 179: /** TokenHelper errors */ 181, 180: @@ -184,3 +183,49 @@ error TokenHelper__TransferFailed(IERC20 token, address recipient, uint256 amoun 184, 183: /** LBQuoter errors */ 185, 184: 186, 185: error LBQuoter_InvalidLength(); + 186:+ + 187:+library Validation { + 188:+ function valid_id(int256 _id) pure internal { + 189:+ if (_id < 0 || uint256(_id) > type(uint24).max) revert IdOverflows(_id); + 190:+ } + 191:+ + 192:+ function is_address_zero(address a) pure internal { + 193:+ if (a == address(0)) revert AddressZero(); + 194:+ } + 195:+ + 196:+ function valid_liquidity(uint256 a, uint256 b) pure internal { + 197:+ if (a == 0 || b == 0) revert InsufficientLiquidity(); + 198:+ } + 199:+ + 200:+ function bin_step_has_no_preset(bytes32 preset, uint16 binStep) pure internal { + 201:+ if (preset == bytes32(0)) revert LBFactory__BinStepHasNoPreset(binStep); + 202:+ } + 203:+ + 204:+ function is_valid_length(uint256 length) pure internal { + 205:+ if (length < 2) { + 206:+ revert LBQuoter_InvalidLength(); + 207:+ } + 208:+ } + 209:+ + 210:+ function is_valid_tokens(IERC20 a, IERC20 b) pure internal { + 211:+ if (a != b) revert LBRouter__WrongTokenOrder(); + 212:+ } + 213:+ + 214:+ function amount_out_is_sufficient(uint256 min, uint256 out) pure internal { + 215:+ if (min > out) revert LBRouter__InsufficientAmountOut(min, out); + 216:+ } + 217:+ + 218:+ function is_valid_token_path(IERC20 pl, IERC20 pr) pure internal { + 219:+ if (pl != pr) + 220:+ revert LBRouter__InvalidTokenPath(address(pl)); + 221:+ } + 222:+ + 223:+ function is_max_amount_exceeded(uint256 _in, uint256 max) pure internal { + 224:+ if (_in > max) revert LBRouter__MaxAmountInExceeded(max, _in); + 225:+ } + 226:+ + 227:+ function caugth_amount_slippage(uint256 xAdded, uint256 minXAdded, uint256 yAdded, uint256 minYAdded) pure internal { + 228:+ if (xAdded < minXAdded || yAdded < minYAdded) + 229:+ revert LBRouter__AmountSlippageCaught(minXAdded, xAdded, minYAdded, yAdded); + 230:+ } + 231:+} \ No newline at end of file
diff --git a/src/LBFactory.sol b/src/LBFactory.sol index 32ee39c..b00b22a 100644 --- a/src/LBFactory.sol +++ b/src/LBFactory.sol @@ -133,7 +133,7 @@ contract LBFactory is PendingOwnable, ILBFactory { 133, 133: ) 134, 134: { 135, 135: bytes32 _preset = _presets[_binStep]; - 136 :- if (_preset == bytes32(0)) revert LBFactory__BinStepHasNoPreset(_binStep); + 136:+ Validation.bin_step_has_no_preset(_preset, _binStep); 137, 137: 138, 138: uint256 _shift; 139, 139: @@ -251,12 +251,12 @@ contract LBFactory is PendingOwnable, ILBFactory { 251, 251: // We sort token for storage efficiency, only one input needs to be stored 252, 252: (IERC20 _tokenA, IERC20 _tokenB) = _sortTokens(_tokenX, _tokenY); 253, 253: // single check is sufficient - 254 :- if (address(_tokenA) == address(0)) revert LBFactory__AddressZero(); + 254:+ Validation.is_address_zero(address(_tokenA)); 255, 255: if (address(_LBPairsInfo[_tokenA][_tokenB][_binStep].LBPair) != address(0)) 256, 256: revert LBFactory__LBPairAlreadyExists(_tokenX, _tokenY, _binStep); 257, 257: 258, 258: bytes32 _preset = _presets[_binStep]; - 259 :- if (_preset == bytes32(0)) revert LBFactory__BinStepHasNoPreset(_binStep); + 259:+ Validation.bin_step_has_no_preset(_preset, _binStep); 260, 260: 261, 261: uint256 _sampleLifetime = _preset.decode(type(uint16).max, 240); 262, 262: // We remove the bits that are not part of the feeParameters @@ -318,7 +318,7 @@ contract LBFactory is PendingOwnable, ILBFactory { 318, 318: (IERC20 _tokenA, IERC20 _tokenB) = _sortTokens(_tokenX, _tokenY); 319, 319: 320, 320: LBPairInformation memory _LBPairInformation = _LBPairsInfo[_tokenA][_tokenB][_binStep]; - 321 :- if (address(_LBPairInformation.LBPair) == address(0)) revert LBFactory__AddressZero(); + 321:+ Validation.is_address_zero(address(_LBPairInformation.LBPair)); 322, 322: 323, 323: if (_LBPairInformation.ignoredForRouting == _ignored) revert LBFactory__LBPairIgnoredIsAlreadyInTheSameState(); 324, 324: @@ -394,7 +394,7 @@ contract LBFactory is PendingOwnable, ILBFactory { 394, 394: /// @notice Remove the preset linked to a binStep 395, 395: /// @param _binStep The bin step to remove 396, 396: function removePreset(uint16 _binStep) external override onlyOwner { - 397 :- if (_presets[_binStep] == bytes32(0)) revert LBFactory__BinStepHasNoPreset(_binStep); + 397:+ Validation.bin_step_has_no_preset(_presets[_binStep], _binStep); 398, 398: 399, 399: // Set the bit `_binStep` to 0 400, 400: bytes32 _avPresets = _availablePresets; @@ -508,7 +508,7 @@ contract LBFactory is PendingOwnable, ILBFactory { 508, 508: /// @notice Internal function to set the recipient of the fee 509, 509: /// @param _feeRecipient The address of the recipient 510, 510: function _setFeeRecipient(address _feeRecipient) internal { - 511 :- if (_feeRecipient == address(0)) revert LBFactory__AddressZero(); + 511:+ Validation.is_address_zero(_feeRecipient); 512, 512: 513, 513: address _oldFeeRecipient = feeRecipient; 514, 514: if (_oldFeeRecipient == _feeRecipient) revert LBFactory__SameFeeRecipient(_feeRecipient);
diff --git a/src/LBPair.sol b/src/LBPair.sol index 717270e..cad9f06 100644 --- a/src/LBPair.sol +++ b/src/LBPair.sol @@ -88,7 +88,7 @@ contract LBPair is LBToken, ReentrancyGuardUpgradeable, ILBPair { 88, 88: /// @notice Set the factory address 89, 89: /// @param _factory The address of the factory 90, 90: constructor(ILBFactory _factory) LBToken() { - 91 :- if (address(_factory) == address(0)) revert LBPair__AddressZero(); + 91:+ Validation.is_address_zero(address(_factory)); 92, 92: factory = _factory; 93, 93: } 94, 94: @@ -108,7 +108,8 @@ contract LBPair is LBToken, ReentrancyGuardUpgradeable, ILBPair { 108, 108: uint16 _sampleLifetime, 109, 109: bytes32 _packedFeeParameters 110, 110: ) external override onlyFactory { - 111 :- if (address(_tokenX) == address(0) || address(_tokenY) == address(0)) revert LBPair__AddressZero(); + 111:+ Validation.is_address_zero(address(_tokenX)); + 112:+ Validation.is_address_zero(address(_tokenY)); 112, 113: if (address(tokenX) != address(0)) revert LBPair__AlreadyInitialized(); 113, 114: 114, 115: __ReentrancyGuard_init();
diff --git a/src/LBQuoter.sol b/src/LBQuoter.sol index 53fdf0c..342ef5c 100644 --- a/src/LBQuoter.sol +++ b/src/LBQuoter.sol @@ -56,9 +56,7 @@ contract LBQuoter { 56, 56: view 57, 57: returns (Quote memory quote) 58, 58: { - 59 :- if (_route.length < 2) { - 60 :- revert LBQuoter_InvalidLength(); - 61 :- } + 59:+ Validation.is_valid_length(_route.length); 62, 60: 63, 61: quote.route = _route; 64, 62: @@ -136,9 +134,7 @@ contract LBQuoter { 136, 134: view 137, 135: returns (Quote memory quote) 138, 136: { - 139 :- if (_route.length < 2) { - 140 :- revert LBQuoter_InvalidLength(); - 141 :- } + 137:+ Validation.is_valid_length(_route.length); 142, 138: quote.route = _route; 143, 139: 144, 140: uint256 swapLength = _route.length - 1;
diff --git a/src/LBRouter.sol b/src/LBRouter.sol index 567c49a..64c34d0 100644 --- a/src/LBRouter.sol +++ b/src/LBRouter.sol @@ -214,7 +214,7 @@ contract LBRouter is ILBRouter { 214, 214: _liquidityParameters.tokenY, 215, 215: _liquidityParameters.binStep 216, 216: ); - 217 :- if (_liquidityParameters.tokenX != _LBPair.tokenX()) revert LBRouter__WrongTokenOrder(); + 217:+ Validation.is_valid_tokens(_liquidityParameters.tokenX, _LBPair.tokenX()); 218, 218: 219, 219: _liquidityParameters.tokenX.safeTransferFrom(msg.sender, address(_LBPair), _liquidityParameters.amountX); 220, 220: _liquidityParameters.tokenY.safeTransferFrom(msg.sender, address(_LBPair), _liquidityParameters.amountY); @@ -238,7 +238,7 @@ contract LBRouter is ILBRouter { 238, 238: _liquidityParameters.tokenY, 239, 239: _liquidityParameters.binStep 240, 240: ); - 241 :- if (_liquidityParameters.tokenX != _LBPair.tokenX()) revert LBRouter__WrongTokenOrder(); + 241:+ Validation.is_valid_tokens(_liquidityParameters.tokenX, _LBPair.tokenX()); 242, 242: 243, 243: if (_liquidityParameters.tokenX == wavax && _liquidityParameters.amountX == msg.value) { 244, 244: _wavaxDepositAndTransfer(address(_LBPair), msg.value); @@ -363,7 +363,7 @@ contract LBRouter is ILBRouter { 363, 363: 364, 364: amountOut = _swapExactTokensForTokens(_amountIn, _pairs, _pairBinSteps, _tokenPath, _to); 365, 365: - 366 :- if (_amountOutMin > amountOut) revert LBRouter__InsufficientAmountOut(_amountOutMin, amountOut); + 366:+ Validation.amount_out_is_sufficient(_amountOutMin, amountOut); 367, 367: } 368, 368: 369, 369: /// @notice Swaps exact tokens for AVAX while performing safety checks @@ -382,8 +382,7 @@ contract LBRouter is ILBRouter { 382, 382: address payable _to, 383, 383: uint256 _deadline 384, 384: ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { - 385 :- if (_tokenPath[_pairBinSteps.length] != IERC20(wavax)) - 386 :- revert LBRouter__InvalidTokenPath(address(_tokenPath[_pairBinSteps.length])); + 385:+ Validation.is_valid_token_path(_tokenPath[_pairBinSteps.length], IERC20(wavax)); 387, 386: 388, 387: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 389, 388: @@ -391,7 +390,7 @@ contract LBRouter is ILBRouter { 391, 390: 392, 391: amountOut = _swapExactTokensForTokens(_amountIn, _pairs, _pairBinSteps, _tokenPath, address(this)); 393, 392: - 394 :- if (_amountOutMinAVAX > amountOut) revert LBRouter__InsufficientAmountOut(_amountOutMinAVAX, amountOut); + 393:+ Validation.amount_out_is_sufficient(_amountOutMinAVAX, amountOut); 395, 394: 396, 395: wavax.withdraw(amountOut); 397, 396: _safeTransferAVAX(_to, amountOut); @@ -417,7 +416,7 @@ contract LBRouter is ILBRouter { 417, 416: 418, 417: amountOut = _swapExactTokensForTokens(msg.value, _pairs, _pairBinSteps, _tokenPath, _to); 419, 418: - 420 :- if (_amountOutMin > amountOut) revert LBRouter__InsufficientAmountOut(_amountOutMin, amountOut); + 419:+ Validation.amount_out_is_sufficient(_amountOutMin, amountOut); 421, 420: } 422, 421: 423, 422: /// @notice Swaps tokens for exact tokens while performing safety checks @@ -439,13 +438,13 @@ contract LBRouter is ILBRouter { 439, 438: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 440, 439: amountsIn = _getAmountsIn(_pairBinSteps, _pairs, _tokenPath, _amountOut); 441, 440: - 442 :- if (amountsIn[0] > _amountInMax) revert LBRouter__MaxAmountInExceeded(_amountInMax, amountsIn[0]); + 441:+ Validation.is_max_amount_exceeded(amountsIn[0], _amountInMax); 443, 442: 444, 443: _tokenPath[0].safeTransferFrom(msg.sender, _pairs[0], amountsIn[0]); 445, 444: 446, 445: uint256 _amountOutReal = _swapTokensForExactTokens(_pairs, _pairBinSteps, _tokenPath, amountsIn, _to); 447, 446: - 448 :- if (_amountOutReal < _amountOut) revert LBRouter__InsufficientAmountOut(_amountOut, _amountOutReal); + 447:+ Validation.amount_out_is_sufficient(_amountOut, _amountOutReal); 449, 448: } 450, 449: 451, 450: /// @notice Swaps tokens for exact AVAX while performing safety checks @@ -464,19 +463,18 @@ contract LBRouter is ILBRouter { 464, 463: address payable _to, 465, 464: uint256 _deadline 466, 465: ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256[] memory amountsIn) { - 467 :- if (_tokenPath[_pairBinSteps.length] != IERC20(wavax)) - 468 :- revert LBRouter__InvalidTokenPath(address(_tokenPath[_pairBinSteps.length])); + 466:+ Validation.is_valid_token_path(_tokenPath[_pairBinSteps.length], IERC20(wavax)); 469, 467: 470, 468: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 471, 469: amountsIn = _getAmountsIn(_pairBinSteps, _pairs, _tokenPath, _amountAVAXOut); 472, 470: - 473 :- if (amountsIn[0] > _amountInMax) revert LBRouter__MaxAmountInExceeded(_amountInMax, amountsIn[0]); + 471:+ Validation.is_max_amount_exceeded(amountsIn[0], _amountInMax); 474, 472: 475, 473: _tokenPath[0].safeTransferFrom(msg.sender, _pairs[0], amountsIn[0]); 476, 474: 477, 475: uint256 _amountOutReal = _swapTokensForExactTokens(_pairs, _pairBinSteps, _tokenPath, amountsIn, address(this)); 478, 476: - 479 :- if (_amountOutReal < _amountAVAXOut) revert LBRouter__InsufficientAmountOut(_amountAVAXOut, _amountOutReal); + 477:+ Validation.amount_out_is_sufficient(_amountAVAXOut, _amountOutReal); 480, 478: 481, 479: wavax.withdraw(_amountOutReal); 482, 480: _safeTransferAVAX(_to, _amountOutReal); @@ -504,18 +502,18 @@ contract LBRouter is ILBRouter { 504, 502: verifyInputs(_pairBinSteps, _tokenPath) 505, 503: returns (uint256[] memory amountsIn) 506, 504: { - 507 :- if (_tokenPath[0] != IERC20(wavax)) revert LBRouter__InvalidTokenPath(address(_tokenPath[0])); + 505:+ Validation.is_valid_token_path(_tokenPath[0], IERC20(wavax)); 508, 506: 509, 507: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 510, 508: amountsIn = _getAmountsIn(_pairBinSteps, _pairs, _tokenPath, _amountOut); 511, 509: - 512 :- if (amountsIn[0] > msg.value) revert LBRouter__MaxAmountInExceeded(msg.value, amountsIn[0]); + 510:+ Validation.is_max_amount_exceeded(amountsIn[0], msg.value); 513, 511: 514, 512: _wavaxDepositAndTransfer(_pairs[0], amountsIn[0]); 515, 513: 516, 514: uint256 _amountOutReal = _swapTokensForExactTokens(_pairs, _pairBinSteps, _tokenPath, amountsIn, _to); 517, 515: - 518 :- if (_amountOutReal < _amountOut) revert LBRouter__InsufficientAmountOut(_amountOut, _amountOutReal); + 516:+ Validation.amount_out_is_sufficient(_amountOut, _amountOutReal); 519, 517: 520, 518: if (msg.value > amountsIn[0]) _safeTransferAVAX(_to, amountsIn[0] - msg.value); 521, 519: } @@ -547,7 +545,7 @@ contract LBRouter is ILBRouter { 547, 545: _swapSupportingFeeOnTransferTokens(_pairs, _pairBinSteps, _tokenPath, _to); 548, 546: 549, 547: amountOut = _targetToken.balanceOf(_to) - _balanceBefore; - 550 :- if (_amountOutMin > amountOut) revert LBRouter__InsufficientAmountOut(_amountOutMin, amountOut); + 548:+ Validation.amount_out_is_sufficient(_amountOutMin, amountOut); 551, 549: } 552, 550: 553, 551: /// @notice Swaps exact tokens for AVAX while performing safety checks supporting for fee on transfer tokens @@ -566,8 +564,7 @@ contract LBRouter is ILBRouter { 566, 564: address payable _to, 567, 565: uint256 _deadline 568, 566: ) external override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { - 569 :- if (_tokenPath[_pairBinSteps.length] != IERC20(wavax)) - 570 :- revert LBRouter__InvalidTokenPath(address(_tokenPath[_pairBinSteps.length])); + 567:+ Validation.is_valid_token_path(_tokenPath[_pairBinSteps.length], IERC20(wavax)); 571, 568: 572, 569: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 573, 570: @@ -578,7 +575,7 @@ contract LBRouter is ILBRouter { 578, 575: _swapSupportingFeeOnTransferTokens(_pairs, _pairBinSteps, _tokenPath, address(this)); 579, 576: 580, 577: amountOut = wavax.balanceOf(address(this)) - _balanceBefore; - 581 :- if (_amountOutMinAVAX > amountOut) revert LBRouter__InsufficientAmountOut(_amountOutMinAVAX, amountOut); + 578:+ Validation.amount_out_is_sufficient(_amountOutMinAVAX, amountOut); 582, 579: 583, 580: wavax.withdraw(amountOut); 584, 581: _safeTransferAVAX(_to, amountOut); @@ -598,7 +595,7 @@ contract LBRouter is ILBRouter { 598, 595: address _to, 599, 596: uint256 _deadline 600, 597: ) external payable override ensure(_deadline) verifyInputs(_pairBinSteps, _tokenPath) returns (uint256 amountOut) { - 601 :- if (_tokenPath[0] != IERC20(wavax)) revert LBRouter__InvalidTokenPath(address(_tokenPath[0])); + 598:+ Validation.is_valid_token_path(_tokenPath[0], IERC20(wavax)); 602, 599: 603, 600: address[] memory _pairs = _getPairs(_pairBinSteps, _tokenPath); 604, 601: @@ -611,7 +608,7 @@ contract LBRouter is ILBRouter { 611, 608: _swapSupportingFeeOnTransferTokens(_pairs, _pairBinSteps, _tokenPath, _to); 612, 609: 613, 610: amountOut = _targetToken.balanceOf(_to) - _balanceBefore; - 614 :- if (_amountOutMin > amountOut) revert LBRouter__InsufficientAmountOut(_amountOutMin, amountOut); + 611:+ Validation.amount_out_is_sufficient(_amountOutMin, amountOut); 615, 612: } 616, 613: 617, 614: /// @notice Unstuck tokens that are sent to this contract by mistake @@ -673,7 +670,7 @@ contract LBRouter is ILBRouter { 673, 670: depositIds = new uint256[](_liq.deltaIds.length); 674, 671: for (uint256 i; i < depositIds.length; ++i) { 675, 672: int256 _id = int256(_activeId) + _liq.deltaIds[i]; - 676 :- if (_id < 0 || uint256(_id) > type(uint24).max) revert LBRouter__IdOverflows(_id); + 673:+ Validation.valid_id(_id); 677, 674: depositIds[i] = uint256(_id); 678, 675: } 679, 676: @@ -687,8 +684,7 @@ contract LBRouter is ILBRouter { 687, 684: _liq.to 688, 685: ); 689, 686: - 690 :- if (_amountXAdded < _liq.amountXMin || _amountYAdded < _liq.amountYMin) - 691 :- revert LBRouter__AmountSlippageCaught(_liq.amountXMin, _amountXAdded, _liq.amountYMin, _amountYAdded); + 687:+ Validation.caugth_amount_slippage(_amountXAdded, _liq.amountXMin, _amountYAdded, _liq.amountYMin); 692, 688: } 693, 689: } 694, 690: @@ -748,8 +744,7 @@ contract LBRouter is ILBRouter { 748, 744: ) private returns (uint256 amountX, uint256 amountY) { 749, 745: ILBToken(address(_LBPair)).safeBatchTransferFrom(msg.sender, address(_LBPair), _ids, _amounts); 750, 746: (amountX, amountY) = _LBPair.burn(_ids, _amounts, _to ... See the rest this report [here](https://github.com/code-423n4/2022-10-traderjoe-findings/blob/main/data/pfapostol-G.md)
#0 - GalloDaSballo
2022-11-09T23:39:37Z
##ย Inline Modifier Will award 1k
1k
1k
1k
Else 88
Very good submission!
4088
#1 - c4-judge
2022-11-16T21:25:37Z
GalloDaSballo marked the issue as grade-a