Sublime contest - IllIllI's results

Democratizing credit via Web3.

General Information

Platform: Code4rena

Start Date: 29/03/2022

Pot Size: $30,000 USDC

Total HM: 6

Participants: 24

Period: 3 days

Judge: HardlyDifficult

Total Solo HM: 4

Id: 101

League: ETH

Sublime

Findings Distribution

Researcher Performance

Rank: 7/24

Findings: 2

Award: $762.33

๐ŸŒŸ Selected for report: 1

๐Ÿš€ Solo Findings: 0

Findings Information

Awards

420.4341 USDC - $420.43

Labels

bug
QA (Quality Assurance)

External Links

Low Risk Issues

Return code of transfer() not checked

The ERC20 standard says that transfer() and transferFrom() return boolean values to indicate whether the operation succeeded or not. While most implementations choose to revert() if the return value will be false, some do not.

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 327)
        IERC20(_borrowAsset).transfer(_to, _fee);

Return code of approve() not checked

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 267)
            SAVINGS_ACCOUNT.approve(_borrowAsset, address(POOLED_CREDIT_LINE), type(uint256).max);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 755)
            IERC20(_collateralAsset).approve(_strategy, _amount);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1025)
        IERC20(_borrowAsset).approve(_strategy, _amount);

Contracts implementing an interface should inherit from that interface

  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 25)
contract PooledCreditLine is ReentrancyGuard, OwnableUpgradeable, IPooledCreditLine {

PooledCreditLine implements the functions of ICreditLine, but does not inherit from it. Note that IPooledCreditLine does NOT inherit from ICreditLine.

Comments should make it clear that amounts lent over limit get truncated rather than having the function revert

  1. File: contracts/PooledCreditLine/LenderPool.sol (line2 290-292)
        if (_totalLent.add(_amount) > _maxLent) {
            _amountToLend = _maxLent.sub(_totalLent);
        }

Missing checks for address(0x0) when assigning values to address state variables

  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 593)
        lenderPool = _lenderPool;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 594)
        USDC = _usdc;

Loss of precision due to multiplication on the result of a division

All multiplications should be done first, followed by divisions

  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 823-827)
        uint256 _collateralNeeded = _currentDebt
            .mul(pooledCreditLineConstants[_id].idealCollateralRatio)
            .div(_ratioOfPrices)
            .mul(10**_decimals)
            .div(SCALING_FACTOR);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 944)
            _maxPossible = _totalCollateralToken.mul(_ratioOfPrices).div(_collateralRatio).mul(SCALING_FACTOR).div(10**_decimals);
  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 1246-1248)
            _currentCollateralRatio = calculateTotalCollateralTokens(_id).mul(_ratioOfPrices).div(_currentDebt).mul(SCALING_FACTOR).div(
                10**_decimals
            );

Comment does not match behavior

  1. File: contracts/Verification/twitterVerifier.sol (line 105)
     * @dev only owner can register users

Upgradeable contract is missing a __gap[50] storage variable to allow for new storage variables in later versions

See this link for a description of this storage variable. While some contracts may not currently be sub-classed, adding the variable now protects against forgetting to add it in the future.

  1. File: contracts/Verification/twitterVerifier.sol (line 10)
contract TwitterVerifier is Initializable, IVerifier, OwnableUpgradeable, EIP712Upgradeable {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 25)
contract LenderPool is ERC1155Upgradeable, ReentrancyGuard, OwnableUpgradeable, IPooledCreditLineEnums, ILenderPool {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 25)
contract PooledCreditLine is ReentrancyGuard, OwnableUpgradeable, IPooledCreditLine {

Non-critical Issues

safeApprove() is deprecated

Deprecated in favor of safeIncreaseAllowance() and safeDecreaseAllowance()

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 335)
        IERC20(_borrowAsset).safeApprove(_strategy, _amount);

public functions not called by the contract should be declared external instead

Contracts are allowed to override their parents' functions and change the visibility from external to public.

  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1189)
    function getPrincipal(uint256 _id) public view override returns (uint256) {

The nonReentrant modifier should occur before all other modifiers

This is a best-practice to protect against reentrancy in other modifiers

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 256)
    ) external onlyPooledCreditLine nonReentrant override {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 355)
    function borrowed(uint256 _id, uint256 _sharesBorrowed) external override onlyPooledCreditLine nonReentrant {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 370)
    ) external override onlyPooledCreditLine nonReentrant {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 394)
    function terminate(uint256 _id, address _to) external override onlyPooledCreditLine nonReentrant {

NatSpec missing @return

  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 577-579)
     * @param _lender lender whose share of prinipal is to be withdrawn
     */
    function calculatePrincipalWithdrawable(uint256 _id, address _lender) external returns (uint256) {
  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 770-772)
     * @param _lender address of the lender for which query is made
     */
    function getLenderInfo(uint256 _id, address _lender) external view returns (LenderInfo memory) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1075-1077)
     * @param _id identifier for the pooled credit line
     */
    function liquidate(uint256 _id) external override nonReentrant onlyLenderPool returns (address, uint256) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1187-1189)
     * @param _id identifier for the pooled credit line
     */
    function getPrincipal(uint256 _id) public view override returns (uint256) {

Typos

  1. File: contracts/Verification/twitterVerifier.sol (line 81)
    /// @param _name name of the verifier (used in domain seperator)

seperator

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 48)
    //-------------------------------- Global varibales start --------------------------------//

varibales

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 61)
     * @param borrowerInterestSharesWithdrawn interest paid by borroower in shares, withdrawn by lender

borroower

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 74)
     * @param borrowLimit max tokens that was reqeuested by borrower

reqeuested

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 143)
     * @param id idenitifer for the pooled credit line

idenitifer

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 156)
     * @notice Emitted when liqudity provided by lender is withdrawn as pool is cancelled

liqudity

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 166)
     * @param shares shares withdrawn by lender from interest accured by yield as well as supplied by borrower

accured

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 185)
    //--------------------------- Globa var update events start ---------------------------//

Globa

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 277)
     * @dev lent amount is deposited to savings account only once borrow limit is reached or if start is callled

callled

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 392)
     * @param _to address to which all the borrow tokens are transfered

transfered

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 577)
     * @param _lender lender whose share of prinipal is to be withdrawn

prinipal

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 606)
     * @notice Function used to liquidate a pooleed credit line

pooleed

  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 228)
     * @notice emitted when threhsolds for one of the parameters is updated

threhsolds

  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 350)
     * @notice emitted when the pooled credit line is terminatd by owner

terminatd

Formatting

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 321)
       if(_totalLent.sub(_fee) < pooledCLConstants[_id].minBorrowAmount) {

if( -> if (

Event is missing indexed fields

Each event should use three indexed fields if there are three or more fields

  1. File: contracts/Verification/twitterVerifier.sol (line 70)
    event SignValidityUpdated(uint256 signValidity);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 147)
    event Lend(uint256 indexed id, address indexed user, uint256 amount);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 154)
    event WithdrawLiquidity(uint256 indexed id, address indexed user, uint256 shares);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 161)
    event WithdrawLiquidityOnCancel(uint256 indexed id, address indexed user, uint256 amount);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 168)
    event InterestWithdrawn(uint256 indexed id, address indexed user, uint256 shares);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 175)
    event LiquidationWithdrawn(uint256 indexed id, address indexed user, uint256 collateralShare);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 181)
    event Liquidated(uint256 indexed id, uint256 collateralLiquidated);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 191)
    event StartFeeFractionUpdated(uint256 updatedStartFeeFraction);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 233)
    event LimitsUpdated(string indexed limitType, uint256 max, uint256 min);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 261)
    event ProtocolFeeFractionUpdated(uint256 updatedProtocolFee);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 285)
    event CollateralDeposited(uint256 indexed id, uint256 amount, address indexed strategy);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 292)
    event CollateralWithdrawn(uint256 indexed id, uint256 amount);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 312)
    event BorrowedFromPooledCreditLine(uint256 indexed id, uint256 borrowAmount);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 319)
    event PooledCreditLineAccepted(uint256 indexed id, uint256 amount);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 327)
    event PartialPooledCreditLineRepaid(uint256 indexed id, address indexed repayer, uint256 repayAmount);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 335)
    event CompletePooledCreditLineRepaid(uint256 indexed id, address indexed repayer, uint256 repayAmount);

Non-exploitable reentrancies

Code should follow the best-practice of the Checks-Effects-Interactions pattern

Reentrancy in TwitterVerifier.registerSelf(bool,uint8,bytes32,bytes32,string,string,uint256) (contracts/Verification/twitterVerifier.sol#115-148): External calls: - verification.registerMasterAddress(msg.sender,_isMasterLinked) (contracts/Verification/twitterVerifier.sol#143) State variables written after the call(s): - hashAddressMap[digest] = msg.sender (contracts/Verification/twitterVerifier.sol#146) - twitterIdMap[_twitterId] = msg.sender (contracts/Verification/twitterVerifier.sol#145) - userData[msg.sender] = UserStructData(_twitterId,_tweetId) (contracts/Verification/twitterVerifier.sol#144) Reentrancy in TwitterVerifier.registerSelf(bool,uint8,bytes32,bytes32,string,string,uint256) (contracts/Verification/twitterVerifier.sol#115-148): External calls: - verification.registerMasterAddress(msg.sender,_isMasterLinked) (contracts/Verification/twitterVerifier.sol#143) Event emitted after the call(s): - UserRegistered(msg.sender,_isMasterLinked,_twitterId) (contracts/Verification/twitterVerifier.sol#147) Reentrancy in TwitterVerifier.unregisterSelf() (contracts/Verification/twitterVerifier.sol#158-165): External calls: - verification.unregisterMasterAddress(msg.sender,address(this)) (contracts/Verification/twitterVerifier.sol#163) Event emitted after the call(s): - UserUnregistered(msg.sender) (contracts/Verification/twitterVerifier.sol#164) Reentrancy in TwitterVerifier.unregisterUser(address) (contracts/Verification/twitterVerifier.sol#171-178): External calls: - verification.unregisterMasterAddress(_user,address(this)) (contracts/Verification/twitterVerifier.sol#176) Event emitted after the call(s): - UserUnregistered(_user) (contracts/Verification/twitterVerifier.sol#177)
Reentrancy in LenderPool._accept(uint256,uint256) (contracts/PooledCreditLine/LenderPool.sol#332-343): External calls: - IERC20(_borrowAsset).safeApprove(_strategy,_amount) (contracts/PooledCreditLine/LenderPool.sol#335) - pooledCLVariables[_id].sharesHeld = SAVINGS_ACCOUNT.deposit(_borrowAsset,_strategy,address(this),_amount) (contracts/PooledCreditLine/LenderPool.sol#336) - POOLED_CREDIT_LINE.accept(_id,_amount) (contracts/PooledCreditLine/LenderPool.sol#338) State variables written after the call(s): - pooledCLConstants[_id].borrowLimit = _amount (contracts/PooledCreditLine/LenderPool.sol#340) - delete pooledCLConstants[_id].startTime (contracts/PooledCreditLine/LenderPool.sol#341) - delete pooledCLConstants[_id].minBorrowAmount (contracts/PooledCreditLine/LenderPool.sol#342) Reentrancy in LenderPool._rebalanceInterestWithdrawn(uint256,uint256,address,address) (contracts/PooledCreditLine/LenderPool.sol#694-742): External calls: - _withdrawInterest(id,from) (contracts/PooledCreditLine/LenderPool.sol#701) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) - _withdrawInterest(id,to) (contracts/PooledCreditLine/LenderPool.sol#702) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) State variables written after the call(s): - _withdrawInterest(id,to) (contracts/PooledCreditLine/LenderPool.sol#702) - pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#439) - pooledCLVariables[_id].lenders[_lender].yieldInterestWithdrawnShares = pooledCLVariables[_id].lenders[_lender].yieldInterestWithdrawnShares.add(_yieldInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#482-485) - pooledCLVariables[_id].lenders[_lender].borrowerInterestSharesWithdrawn = pooledCLVariables[_id].lenders[_lender].borrowerInterestSharesWithdrawn.add(_borrowerInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#486-489) - pooledCLVariables[_id].borrowerInterestSharesWithdrawn = pooledCLVariables[_id].borrowerInterestSharesWithdrawn.add(_borrowerInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#490-492) - pooledCLVariables[_id].yieldInterestWithdrawnShares = pooledCLVariables[_id].yieldInterestWithdrawnShares.add(_yieldInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#493-495) - pooledCLVariables[id].lenders[from].borrowerInterestSharesWithdrawn = pooledCLVariables[id].lenders[from].borrowerInterestSharesWithdrawn.sub(borrowerInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#715-718) - pooledCLVariables[id].lenders[from].yieldInterestWithdrawnShares = pooledCLVariables[id].lenders[from].yieldInterestWithdrawnShares.sub(yieldInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#722-725) - pooledCLVariables[id].lenders[to].borrowerInterestSharesWithdrawn = pooledCLVariables[id].lenders[to].borrowerInterestSharesWithdrawn.add(borrowerInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#730-733) - pooledCLVariables[id].lenders[to].yieldInterestWithdrawnShares = pooledCLVariables[id].lenders[to].yieldInterestWithdrawnShares.add(yieldInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#736-739) Reentrancy in LenderPool._withdrawInterest(uint256,address) (contracts/PooledCreditLine/LenderPool.sol#429-445): External calls: - (_interestToWithdraw,_interestSharesToWithdraw) = _calculateInterestToWithdraw(_id,_lender,_strategy,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#433-438) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) State variables written after the call(s): - pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#439) Reentrancy in LenderPool._withdrawLiquidity(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#524-572): External calls: - _status = POOLED_CREDIT_LINE.getStatus(_id) (contracts/PooledCreditLine/LenderPool.sol#525) - (_interestWithdrawable,_interestSharesWithdrawable) = _calculateInterestToWithdraw(_id,msg.sender,_strategy,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#555-560) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) - _sharesToWithdraw = IYield(_strategy).getSharesForTokens(_amountToWithdraw,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#562) State variables written after the call(s): - pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesWithdrawable) (contracts/PooledCreditLine/LenderPool.sol#563) Reentrancy in LenderPool._withdrawLiquidity(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#524-572): External calls: - _status = POOLED_CREDIT_LINE.getStatus(_id) (contracts/PooledCreditLine/LenderPool.sol#525) - IERC20(_borrowAsset).safeTransfer(msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#546) - (_interestWithdrawable,_interestSharesWithdrawable) = _calculateInterestToWithdraw(_id,msg.sender,_strategy,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#555-560) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) - _sharesToWithdraw = IYield(_strategy).getSharesForTokens(_amountToWithdraw,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#562) - SAVINGS_ACCOUNT.withdrawShares(_borrowAsset,_strategy,msg.sender,_sharesToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#565) - _burn(msg.sender,_id,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#571) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) State variables written after the call(s): - _burn(msg.sender,_id,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#571) - _balances[id][account] = _balances[id][account].sub(amount,ERC1155: burn amount exceeds balance) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#304-307) - _burn(msg.sender,_id,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#571) - pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#439) - pooledCLVariables[id].lenders[from].borrowerInterestSharesWithdrawn = pooledCLVariables[id].lenders[from].borrowerInterestSharesWithdrawn.sub(borrowerInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#715-718) - pooledCLVariables[id].lenders[from].yieldInterestWithdrawnShares = pooledCLVariables[id].lenders[from].yieldInterestWithdrawnShares.sub(yieldInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#722-725) - pooledCLVariables[id].lenders[to].borrowerInterestSharesWithdrawn = pooledCLVariables[id].lenders[to].borrowerInterestSharesWithdrawn.add(borrowerInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#730-733) - pooledCLVariables[_id].lenders[_lender].yieldInterestWithdrawnShares = pooledCLVariables[_id].lenders[_lender].yieldInterestWithdrawnShares.add(_yieldInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#482-485) - pooledCLVariables[_id].lenders[_lender].borrowerInterestSharesWithdrawn = pooledCLVariables[_id].lenders[_lender].borrowerInterestSharesWithdrawn.add(_borrowerInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#486-489) - pooledCLVariables[_id].borrowerInterestSharesWithdrawn = pooledCLVariables[_id].borrowerInterestSharesWithdrawn.add(_borrowerInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#490-492) - pooledCLVariables[id].lenders[to].yieldInterestWithdrawnShares = pooledCLVariables[id].lenders[to].yieldInterestWithdrawnShares.add(yieldInterestOnTransferAmount) (contracts/PooledCreditLine/LenderPool.sol#736-739) - pooledCLVariables[_id].yieldInterestWithdrawnShares = pooledCLVariables[_id].yieldInterestWithdrawnShares.add(_yieldInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#493-495) - _burn(msg.sender,_id,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#571) - totalSupply[id] = totalSupply[id].add(amount) (contracts/PooledCreditLine/LenderPool.sol#677) - totalSupply[id] = supply - amount (contracts/PooledCreditLine/LenderPool.sol#681) Reentrancy in LenderPool.lend(uint256,uint256) (contracts/PooledCreditLine/LenderPool.sol#281-304): External calls: - IERC20(_borrowAsset).safeTransferFrom(msg.sender,address(this),_amountToLend) (contracts/PooledCreditLine/LenderPool.sol#295) - _mint(msg.sender,_id,_amountToLend,) (contracts/PooledCreditLine/LenderPool.sol#296) - IERC1155ReceiverUpgradeable(to).onERC1155Received(operator,from,id,amount,data) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#380-388) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) State variables written after the call(s): - _mint(msg.sender,_id,_amountToLend,) (contracts/PooledCreditLine/LenderPool.sol#296) - totalSupply[id] = totalSupply[id].add(amount) (contracts/PooledCreditLine/LenderPool.sol#677) - totalSupply[id] = supply - amount (contracts/PooledCreditLine/LenderPool.sol#681) Reentrancy in LenderPool.start(uint256,address) (contracts/PooledCreditLine/LenderPool.sol#312-330): External calls: - POOLED_CREDIT_LINE.cancelRequestOnLowCollection(_id) (contracts/PooledCreditLine/LenderPool.sol#322) State variables written after the call(s): - delete pooledCLConstants[_id].startTime (contracts/PooledCreditLine/LenderPool.sol#323) Reentrancy in LenderPool.terminate(uint256,address) (contracts/PooledCreditLine/LenderPool.sol#394-409): External calls: - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#400) - SAVINGS_ACCOUNT.withdrawShares(_borrowAsset,_strategy,_to,_principalWithdrawable.add(_totalInterestInShares),false) (contracts/PooledCreditLine/LenderPool.sol#406) State variables written after the call(s): - delete pooledCLConstants[_id] (contracts/PooledCreditLine/LenderPool.sol#407) - delete pooledCLVariables[_id] (contracts/PooledCreditLine/LenderPool.sol#408) Reentrancy in LenderPool._calculateInterestToWithdraw(uint256,address,address,address) (contracts/PooledCreditLine/LenderPool.sol#447-502): External calls: - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) State variables written after the call(s): - pooledCLVariables[_id].lenders[_lender].yieldInterestWithdrawnShares = pooledCLVariables[_id].lenders[_lender].yieldInterestWithdrawnShares.add(_yieldInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#482-485) - pooledCLVariables[_id].lenders[_lender].borrowerInterestSharesWithdrawn = pooledCLVariables[_id].lenders[_lender].borrowerInterestSharesWithdrawn.add(_borrowerInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#486-489) - pooledCLVariables[_id].borrowerInterestSharesWithdrawn = pooledCLVariables[_id].borrowerInterestSharesWithdrawn.add(_borrowerInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#490-492) - pooledCLVariables[_id].yieldInterestWithdrawnShares = pooledCLVariables[_id].yieldInterestWithdrawnShares.add(_yieldInterestForLender) (contracts/PooledCreditLine/LenderPool.sol#493-495) Reentrancy in LenderPool.liquidate(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#612-627): External calls: - (_collateralAsset,_collateralLiquidated) = POOLED_CREDIT_LINE.liquidate(_id) (contracts/PooledCreditLine/LenderPool.sol#617) State variables written after the call(s): - pooledCLConstants[_id].collateralAsset = _collateralAsset (contracts/PooledCreditLine/LenderPool.sol#618) - pooledCLVariables[_id].collateralHeld = _collateralLiquidated (contracts/PooledCreditLine/LenderPool.sol#619) Reentrancy in LenderPool._withdrawInterest(uint256,address) (contracts/PooledCreditLine/LenderPool.sol#429-445): External calls: - (_interestToWithdraw,_interestSharesToWithdraw) = _calculateInterestToWithdraw(_id,_lender,_strategy,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#433-438) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) Event emitted after the call(s): - InterestWithdrawn(_id,_lender,_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#444) Reentrancy in LenderPool._withdrawLiquidation(uint256,uint256) (contracts/PooledCreditLine/LenderPool.sol#639-655): External calls: - IERC20(pooledCLConstants[_id].collateralAsset).safeTransfer(msg.sender,_lenderCollateralShare) (contracts/PooledCreditLine/LenderPool.sol#651) Event emitted after the call(s): - LiquidationWithdrawn(_id,msg.sender,_lenderCollateralShare) (contracts/PooledCreditLine/LenderPool.sol#652) Reentrancy in LenderPool._withdrawLiquidation(uint256,uint256) (contracts/PooledCreditLine/LenderPool.sol#639-655): External calls: - IERC20(pooledCLConstants[_id].collateralAsset).safeTransfer(msg.sender,_lenderCollateralShare) (contracts/PooledCreditLine/LenderPool.sol#651) - _withdrawLiquidity(_id,true) (contracts/PooledCreditLine/LenderPool.sol#654) - _status = POOLED_CREDIT_LINE.getStatus(_id) (contracts/PooledCreditLine/LenderPool.sol#525) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/SafeERC20.sol#69) - IERC20(_borrowAsset).safeTransfer(msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#546) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#119) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _sharesToWithdraw = IYield(_strategy).getSharesForTokens(_amountToWithdraw,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#562) - SAVINGS_ACCOUNT.withdrawShares(_borrowAsset,_strategy,msg.sender,_sharesToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#565) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) External calls sending eth: - _withdrawLiquidity(_id,true) (contracts/PooledCreditLine/LenderPool.sol#654) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#119) Event emitted after the call(s): - InterestWithdrawn(_id,_lender,_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#444) - _withdrawLiquidity(_id,true) (contracts/PooledCreditLine/LenderPool.sol#654) - TransferSingle(operator,account,address(0),id,amount) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#309) - _withdrawLiquidity(_id,true) (contracts/PooledCreditLine/LenderPool.sol#654) - WithdrawLiquidity(_id,msg.sender,_sharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#566) - _withdrawLiquidity(_id,true) (contracts/PooledCreditLine/LenderPool.sol#654) - WithdrawLiquidityOnCancel(_id,msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#547) - _withdrawLiquidity(_id,true) (contracts/PooledCreditLine/LenderPool.sol#654) Reentrancy in LenderPool._withdrawLiquidity(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#524-572): External calls: - _status = POOLED_CREDIT_LINE.getStatus(_id) (contracts/PooledCreditLine/LenderPool.sol#525) - IERC20(_borrowAsset).safeTransfer(msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#546) Event emitted after the call(s): - WithdrawLiquidityOnCancel(_id,msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#547) Reentrancy in LenderPool._withdrawLiquidity(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#524-572): External calls: - _status = POOLED_CREDIT_LINE.getStatus(_id) (contracts/PooledCreditLine/LenderPool.sol#525) - (_interestWithdrawable,_interestSharesWithdrawable) = _calculateInterestToWithdraw(_id,msg.sender,_strategy,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#555-560) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) - _sharesToWithdraw = IYield(_strategy).getSharesForTokens(_amountToWithdraw,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#562) - SAVINGS_ACCOUNT.withdrawShares(_borrowAsset,_strategy,msg.sender,_sharesToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#565) Event emitted after the call(s): - WithdrawLiquidity(_id,msg.sender,_sharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#566) Reentrancy in LenderPool._withdrawLiquidity(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#524-572): External calls: - _status = POOLED_CREDIT_LINE.getStatus(_id) (contracts/PooledCreditLine/LenderPool.sol#525) - IERC20(_borrowAsset).safeTransfer(msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#546) - (_interestWithdrawable,_interestSharesWithdrawable) = _calculateInterestToWithdraw(_id,msg.sender,_strategy,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#555-560) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) - _sharesToWithdraw = IYield(_strategy).getSharesForTokens(_amountToWithdraw,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#562) - SAVINGS_ACCOUNT.withdrawShares(_borrowAsset,_strategy,msg.sender,_sharesToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#565) - _burn(msg.sender,_id,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#571) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) Event emitted after the call(s): - InterestWithdrawn(_id,_lender,_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#444) - _burn(msg.sender,_id,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#571) - TransferSingle(operator,account,address(0),id,amount) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#309) - _burn(msg.sender,_id,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#571) Reentrancy in LenderPool.lend(uint256,uint256) (contracts/PooledCreditLine/LenderPool.sol#281-304): External calls: - IERC20(_borrowAsset).safeTransferFrom(msg.sender,address(this),_amountToLend) (contracts/PooledCreditLine/LenderPool.sol#295) - _mint(msg.sender,_id,_amountToLend,) (contracts/PooledCreditLine/LenderPool.sol#296) - IERC1155ReceiverUpgradeable(to).onERC1155Received(operator,from,id,amount,data) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#380-388) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) Event emitted after the call(s): - InterestWithdrawn(_id,_lender,_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#444) - _mint(msg.sender,_id,_amountToLend,) (contracts/PooledCreditLine/LenderPool.sol#296) - Lend(_id,msg.sender,_amount) (contracts/PooledCreditLine/LenderPool.sol#298) - TransferSingle(operator,address(0),account,id,amount) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#258) - _mint(msg.sender,_id,_amountToLend,) (contracts/PooledCreditLine/LenderPool.sol#296) Reentrancy in LenderPool.liquidate(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#612-627): External calls: - (_collateralAsset,_collateralLiquidated) = POOLED_CREDIT_LINE.liquidate(_id) (contracts/PooledCreditLine/LenderPool.sol#617) Event emitted after the call(s): - Liquidated(_id,_collateralLiquidated) (contracts/PooledCreditLine/LenderPool.sol#621) Reentrancy in LenderPool.liquidate(uint256,bool) (contracts/PooledCreditLine/LenderPool.sol#612-627): External calls: - (_collateralAsset,_collateralLiquidated) = POOLED_CREDIT_LINE.liquidate(_id) (contracts/PooledCreditLine/LenderPool.sol#617) - _withdrawLiquidation(_id,_lendingShare) (contracts/PooledCreditLine/LenderPool.sol#625) - _status = POOLED_CREDIT_LINE.getStatus(_id) (contracts/PooledCreditLine/LenderPool.sol#525) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/SafeERC20.sol#69) - IERC20(_borrowAsset).safeTransfer(msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#546) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#119) - IERC20(pooledCLConstants[_id].collateralAsset).safeTransfer(msg.sender,_lenderCollateralShare) (contracts/PooledCreditLine/LenderPool.sol#651) - _notBorrowedInShares = IYield(_strategy).getSharesForTokens(_notBorrowed,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#460) - SAVINGS_ACCOUNT.withdraw(_borrowAsset,_strategy,_lender,_interestToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#442) - _sharesToWithdraw = IYield(_strategy).getSharesForTokens(_amountToWithdraw,_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#562) - SAVINGS_ACCOUNT.withdrawShares(_borrowAsset,_strategy,msg.sender,_sharesToWithdraw,false) (contracts/PooledCreditLine/LenderPool.sol#565) - _interestToWithdraw = IYield(_strategy).getTokensForShares(_yieldInterestForLender.add(_borrowerInterestForLender),_borrowAsset) (contracts/PooledCreditLine/LenderPool.sol#497-500) External calls sending eth: - _withdrawLiquidation(_id,_lendingShare) (contracts/PooledCreditLine/LenderPool.sol#625) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#119) Event emitted after the call(s): - InterestWithdrawn(_id,_lender,_interestSharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#444) - _withdrawLiquidation(_id,_lendingShare) (contracts/PooledCreditLine/LenderPool.sol#625) - LiquidationWithdrawn(_id,msg.sender,_lenderCollateralShare) (contracts/PooledCreditLine/LenderPool.sol#652) - _withdrawLiquidation(_id,_lendingShare) (contracts/PooledCreditLine/LenderPool.sol#625) - TransferSingle(operator,account,address(0),id,amount) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol#309) - _withdrawLiquidation(_id,_lendingShare) (contracts/PooledCreditLine/LenderPool.sol#625) - WithdrawLiquidity(_id,msg.sender,_sharesToWithdraw) (contracts/PooledCreditLine/LenderPool.sol#566) - _withdrawLiquidation(_id,_lendingShare) (contracts/PooledCreditLine/LenderPool.sol#625) - WithdrawLiquidityOnCancel(_id,msg.sender,_liquidityProvided) (contracts/PooledCreditLine/LenderPool.sol#547) - _withdrawLiquidation(_id,_lendingShare) (contracts/PooledCreditLine/LenderPool.sol#625)
Reentrancy in PooledCreditLine.repay(uint256,uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#976-1017): External calls: - _repaidInterestShares = IYield(pooledCreditLineConstants[_id].borrowAssetStrategy).getSharesForTokens(_interestPaid,pooledCreditLineConstants[_id].borrowAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#1006-1009) - _repaidShares = _repay(_id,_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#1010) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/SafeERC20.sol#69) - _sharesReceived = IYield(_strategy).getSharesForTokens(_amount,_borrowAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#1023) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#119) - IERC20(_borrowAsset).safeTransferFrom(msg.sender,address(this),_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#1024) - IERC20(_borrowAsset).approve(_strategy,_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#1025) - _savingsAccount.deposit(_borrowAsset,_strategy,lenderPool,_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#1026) - ILenderPool(lenderPool).repaid(_id,_repaidShares,_repaidInterestShares) (contracts/PooledCreditLine/PooledCreditLine.sol#1011) External calls sending eth: - _repaidShares = _repay(_id,_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#1010) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#119) State variables written after the call(s): - pooledCreditLineVariables[_id].status = PooledCreditLineStatus.CLOSED (contracts/PooledCreditLine/PooledCreditLine.sol#1014) Reentrancy in PooledCreditLine._borrow(uint256,uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#897-918): External calls: - require(bool,string)(_amount <= calculateBorrowableAmount(_id),B3) (contracts/PooledCreditLine/PooledCreditLine.sol#900) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _sharesWithdrawn = _withdrawBorrowAmount(_borrowAsset,pooledCreditLineConstants[_id].borrowAssetStrategy,_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#905) - _shares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#961) - _savingsAccount.withdrawFrom(_asset,_strategy,lenderPool,address(this),_amountInTokens,false) (contracts/PooledCreditLine/PooledCreditLine.sol#962) - ILenderPool(lenderPool).borrowed(_id,_sharesWithdrawn) (contracts/PooledCreditLine/PooledCreditLine.sol#906) State variables written after the call(s): - updateStateOnPrincipalChange(_id,pooledCreditLineVariables[_id].principal.add(_borrowedAmount)) (contracts/PooledCreditLine/PooledCreditLine.sol#910) - pooledCreditLineVariables[_id].interestAccruedTillLastPrincipalUpdate = _totalInterestAccrued (contracts/PooledCreditLine/PooledCreditLine.sol#1225) - pooledCreditLineVariables[_id].lastPrincipalUpdateTime = block.timestamp (contracts/PooledCreditLine/PooledCreditLine.sol#1226) - pooledCreditLineVariables[_id].principal = _updatedPrincipal (contracts/PooledCreditLine/PooledCreditLine.sol#1227) Reentrancy in PooledCreditLine._withdrawCollateral(uint256,bool) (contracts/PooledCreditLine/PooledCreditLine.sol#795-802): External calls: - _withdrawableCollateral = withdrawableCollateral(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#796) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_withdrawableCollateral,_toSavingsAccount) (contracts/PooledCreditLine/PooledCreditLine.sol#800) - _amountInShares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#842) - _amountReceived = _savingsAccount.transferShares(_amountInShares,_asset,_strategy,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#849) - _amountReceived = _savingsAccount.withdrawShares(_asset,_strategy,msg.sender,_amountInShares,false) (contracts/PooledCreditLine/PooledCreditLine.sol#851) State variables written after the call(s): - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_withdrawableCollateral,_toSavingsAccount) (contracts/PooledCreditLine/PooledCreditLine.sol#800) - depositedCollateralInShares[_id] = depositedCollateralInShares[_id].sub(_amountInShares) (contracts/PooledCreditLine/PooledCreditLine.sol#846) Reentrancy in PooledCreditLine.liquidate(uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#1077-1107): External calls: - currentCollateralRatio = calculateCurrentCollateralRatio(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1083) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _totalCollateral = calculateTotalCollateralTokens(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1084) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) State variables written after the call(s): - pooledCreditLineVariables[_id].status = PooledCreditLineStatus.LIQUIDATED (contracts/PooledCreditLine/PooledCreditLine.sol#1100) Reentrancy in PooledCreditLine.liquidate(uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#1077-1107): External calls: - currentCollateralRatio = calculateCurrentCollateralRatio(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1083) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _totalCollateral = calculateTotalCollateralTokens(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1084) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _collateralReceived = _transferCollateral(_id,_collateralAsset,_collateralToLiquidate,false) (contracts/PooledCreditLine/PooledCreditLine.sol#1102) - _amountInShares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#842) - _amountReceived = _savingsAccount.transferShares(_amountInShares,_asset,_strategy,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#849) - _amountReceived = _savingsAccount.withdrawShares(_asset,_strategy,msg.sender,_amountInShares,false) (contracts/PooledCreditLine/PooledCreditLine.sol#851) State variables written after the call(s): - _collateralReceived = _transferCollateral(_id,_collateralAsset,_collateralToLiquidate,false) (contracts/PooledCreditLine/PooledCreditLine.sol#1102) - depositedCollateralInShares[_id] = depositedCollateralInShares[_id].sub(_amountInShares) (contracts/PooledCreditLine/PooledCreditLine.sol#846) Reentrancy in PooledCreditLine.terminate(uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#1158-1165): External calls: - _allCollateral = calculateTotalCollateralTokens(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1159) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_allCollateral,false) (contracts/PooledCreditLine/PooledCreditLine.sol#1160) - _amountInShares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#842) - _amountReceived = _savingsAccount.transferShares(_amountInShares,_asset,_strategy,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#849) - _amountReceived = _savingsAccount.withdrawShares(_asset,_strategy,msg.sender,_amountInShares,false) (contracts/PooledCreditLine/PooledCreditLine.sol#851) State variables written after the call(s): - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_allCollateral,false) (contracts/PooledCreditLine/PooledCreditLine.sol#1160) - depositedCollateralInShares[_id] = depositedCollateralInShares[_id].sub(_amountInShares) (contracts/PooledCreditLine/PooledCreditLine.sol#846) - delete pooledCreditLineConstants[_id] (contracts/PooledCreditLine/PooledCreditLine.sol#1162) Reentrancy in PooledCreditLine.withdrawCollateral(uint256,uint256,bool) (contracts/PooledCreditLine/PooledCreditLine.sol#772-781): External calls: - _withdrawableCollateral = withdrawableCollateral(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#777) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_amount,_toSavingsAccount) (contracts/PooledCreditLine/PooledCreditLine.sol#779) - _amountInShares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#842) - _amountReceived = _savingsAccount.transferShares(_amountInShares,_asset,_strategy,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#849) - _amountReceived = _savingsAccount.withdrawShares(_asset,_strategy,msg.sender,_amountInShares,false) (contracts/PooledCreditLine/PooledCreditLine.sol#851) State variables written after the call(s): - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_amount,_toSavingsAccount) (contracts/PooledCreditLine/PooledCreditLine.sol#779) - depositedCollateralInShares[_id] = depositedCollateralInShares[_id].sub(_amountInShares) (contracts/PooledCreditLine/PooledCreditLine.sol#846) Reentrancy in PooledCreditLine._transferCollateral(uint256,address,uint256,bool) (contracts/PooledCreditLine/PooledCreditLine.sol#835-855): External calls: - _amountInShares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#842) State variables written after the call(s): - depositedCollateralInShares[_id] = depositedCollateralInShares[_id].sub(_amountInShares) (contracts/PooledCreditLine/PooledCreditLine.sol#846) Reentrancy in PooledCreditLine.depositCollateral(uint256,uint256,bool) (contracts/PooledCreditLine/PooledCreditLine.sol#739-762): External calls: - _sharesDeposited = _savingsAccount.transferFrom(_collateralAsset,_strategy,msg.sender,address(this),_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#752) - IERC20(_collateralAsset).safeTransferFrom(msg.sender,address(this),_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#754) - IERC20(_collateralAsset).approve(_strategy,_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#755) - _sharesDeposited = _savingsAccount.deposit(_collateralAsset,_strategy,address(this),_amount) (contracts/PooledCreditLine/PooledCreditLine.sol#757) State variables written after the call(s): - depositedCollateralInShares[_id] = depositedCollateralInShares[_id].add(_sharesDeposited) (contracts/PooledCreditLine/PooledCreditLine.sol#759) Reentrancy in PooledCreditLine.terminate(uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#1158-1165): External calls: - _allCollateral = calculateTotalCollateralTokens(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1159) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_allCollateral,false) (contracts/PooledCreditLine/PooledCreditLine.sol#1160) - _amountInShares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#842) - _amountReceived = _savingsAccount.transferShares(_amountInShares,_asset,_strategy,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#849) - _amountReceived = _savingsAccount.withdrawShares(_asset,_strategy,msg.sender,_amountInShares,false) (contracts/PooledCreditLine/PooledCreditLine.sol#851) State variables written after the call(s): - delete pooledCreditLineVariables[_id] (contracts/PooledCreditLine/PooledCreditLine.sol#1161) Reentrancy in PooledCreditLine.cancelRequest(uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#1143-1151): External calls: - ILenderPool(lenderPool).requestCancelled(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1149) Event emitted after the call(s): - PooledCreditLineCancelled(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1150) Reentrancy in PooledCreditLine.request(IPooledCreditLineDeclarations.Request) (contracts/PooledCreditLine/PooledCreditLine.sol#638-669): External calls: - _notifyRequest(_id,_request.lenderVerifier,_request.borrowAsset,_request.borrowAssetStrategy,_request.borrowLimit,_request.minBorrowAmount,_request.collectionPeriod,_request.areTokensTransferable) (contracts/PooledCreditLine/PooledCreditLine.sol#657-666) - ILenderPool(lenderPool).create(_id,_lenderVerifier,_borrowToken,_borrowAssetStrategy,_borrowLimit,_minBorrowedAmount,_collectionPeriod,_areTokensTransferable) (contracts/PooledCreditLine/PooledCreditLine.sol#703-712) Event emitted after the call(s): - PooledCreditLineRequested(_id,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#667) Reentrancy in PooledCreditLine.terminate(uint256) (contracts/PooledCreditLine/PooledCreditLine.sol#1158-1165): External calls: - _allCollateral = calculateTotalCollateralTokens(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1159) - _collateral = IYield(_strategy).getTokensForShares(_collateralShares,_collateralAsset) (contracts/PooledCreditLine/PooledCreditLine.sol#868) - _transferCollateral(_id,pooledCreditLineConstants[_id].collateralAsset,_allCollateral,false) (contracts/PooledCreditLine/PooledCreditLine.sol#1160) - _amountInShares = IYield(_strategy).getSharesForTokens(_amountInTokens,_asset) (contracts/PooledCreditLine/PooledCreditLine.sol#842) - _amountReceived = _savingsAccount.transferShares(_amountInShares,_asset,_strategy,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#849) - _amountReceived = _savingsAccount.withdrawShares(_asset,_strategy,msg.sender,_amountInShares,false) (contracts/PooledCreditLine/PooledCreditLine.sol#851) - ILenderPool(lenderPool).terminate(_id,msg.sender) (contracts/PooledCreditLine/PooledCreditLine.sol#1163) Event emitted after the call(s): - PooledCreditLineTerminated(_id) (contracts/PooledCreditLine/PooledCreditLine.sol#1164)

#0 - ritik99

2022-04-12T21:48:43Z

All suggestions are valid except the ones for order of arithmetic operations, which have been set this way to prevent overflow, and for natspec for registerSelf(), see #81

The report is of high quality

#1 - HardlyDifficult

2022-04-18T15:03:45Z

Findings Information

Awards

341.9032 USDC - $341.90

Labels

bug
G (Gas Optimization)

External Links

Multiple mappings can be combined into a single mapping of a value to a struct

  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 109-121)
    /**
     * @notice Mapping that stores constants for pooledCredit creditLine against it's id
     */
    mapping(uint256 => LenderPoolConstants) public pooledCLConstants;
    /**
     * @notice Mapping that stores variables for pooledCredit creditLine against it's id
     */
    mapping(uint256 => LenderPoolVariables) public pooledCLVariables;
    /**
     * @notice Mapping that stores total pooledCreditLine token supply against the creditLineId
     * @dev Since ERC1155 tokens don't support the totalSupply function it is maintained here
     */
    mapping(uint256 => uint256) public totalSupply;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (lines 184-198)
    /**
     * @notice stores the collateral shares in a pooled credit line per collateral strategy
     * @dev creditLineId => collateralShares
     **/
    mapping(uint256 => uint256) public depositedCollateralInShares;

    /**
     * @notice stores the variables to maintain a pooled credit line
     **/
    mapping(uint256 => PooledCreditLineVariables) public pooledCreditLineVariables;

    /**
     * @notice stores the constants related to a pooled credit line
     **/
    mapping(uint256 => PooledCreditLineConstants) public pooledCreditLineConstants;

++i/i++ should be unchecked{++i}/unchecked{++i} when it is not possible for them to overflow, as is the case when used in for- and while-loops

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 670)
        for (uint256 i; i < ids.length; ++i) {

<array>.length should not be looked up in every loop of a for-loop

Even memory arrays incur the overhead of bit tests and bit shifts to calculate the array length

  1. File: contracts/PooledCreditLine/LenderPool.sol (line 670)
        for (uint256 i; i < ids.length; ++i) {

Using calldata instead of memory for read-only arguments in external functions saves gas

  1. File: contracts/Verification/twitterVerifier.sol (line 88)
        string memory _name,
  1. File: contracts/Verification/twitterVerifier.sol (line 89)
        string memory _version
  1. File: contracts/Verification/twitterVerifier.sol (line 120)
        string memory _twitterId,
  1. File: contracts/Verification/twitterVerifier.sol (line 121)
        string memory _tweetId,

internal functions only called once can be inlined to save gas

  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 694-698)
    function _rebalanceInterestWithdrawn(
        uint256 id,
        uint256 amount,
        address from,
        address to
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 388)
    function _limitBorrowedInUSD(address _borrowToken, uint256 _borrowLimit, uint256 _minBorrowAmount) internal view {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 671)
    function _createRequest(Request calldata _request) internal returns (uint256) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (lines 693-701)
    function _notifyRequest(
        uint256 _id,
        address _lenderVerifier,
        address _borrowToken,
        address _borrowAssetStrategy,
        uint256 _borrowLimit,
        uint256 _minBorrowedAmount,
        uint256 _collectionPeriod,
        bool _areTokensTransferable
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 897)
    function _borrow(uint256 _id, uint256 _amount) internal {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (lines 955-959)
    function _withdrawBorrowAmount(
        address _asset,
        address _strategy,
        uint256 _amountInTokens
    ) internal returns (uint256) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1019)
    function _repay(uint256 _id, uint256 _amount) internal returns (uint256) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1223)
    function updateStateOnPrincipalChange(uint256 _id, uint256 _updatedPrincipal) internal {

Multiple if-statements with mutually-exclusive conditions should be changed to if-else statements

If two conditions are the same, their blocks should be combined

  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 676-688)
            if (from == address(0)) {
                totalSupply[id] = totalSupply[id].add(amount);
            } else if (to == address(0)) {
                uint256 supply = totalSupply[id];
                require(supply >= amount, 'T3');
                totalSupply[id] = supply - amount;
            } else {
                require(pooledCLConstants[id].areTokensTransferable, 'T4');
            }

            if (from == address(0)) {
                return;
            }

Use a more recent version of solidity

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 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

  1. File: contracts/Verification/twitterVerifier.sol (line 2)
pragma solidity 0.7.6;
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 2)
pragma solidity 0.7.6;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 2)
pragma solidity 0.7.6;

Splitting require() statements that use && saves gas

See this issue for an example

  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 642)
        require(_request.borrowAsset != address(0) && _request.collateralAsset != address(0), 'R4');

require() or revert() statements that check input arguments should be at the top of the function

  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 394)
        require(_minBorrowAmount <= _borrowLimit, 'ILB2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 778)
        require(_amount <= _withdrawableCollateral, 'WC1');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 900)
        require(_amount <= calculateBorrowableAmount(_id), 'B3');

State variables should be cached in stack variables rather than re-reading them from storage

The instances below point to the second access of a state variable within a function. Less obvious optimizations include having local storage variables of mappings within state variable mappings or mappings within state variable structs, having local storage variables of structs within mappings, or having local caches of state variable contracts/addresses.

  1. File: contracts/Verification/twitterVerifier.sol (line 209)
        emit SignerUpdated(signerAddress);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 267)
            SAVINGS_ACCOUNT.approve(_borrowAsset, address(POOLED_CREDIT_LINE), type(uint256).max);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 267)
            SAVINGS_ACCOUNT.approve(_borrowAsset, address(POOLED_CREDIT_LINE), type(uint256).max);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 258)
        pooledCLConstants[_id].borrowAsset = _borrowAsset;
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 283)
        require(block.timestamp < pooledCLConstants[_id].startTime, 'L2');
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 318)
        address _borrowAsset = pooledCLConstants[_id].borrowAsset;
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 334)
        address _strategy = pooledCLConstants[_id].borrowAssetStrategy;
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 396)
        address _borrowAsset = pooledCLConstants[_id].borrowAsset;
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 431)
        address _borrowAsset = pooledCLConstants[_id].borrowAsset;
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 534)
                block.timestamp > pooledCLConstants[_id].startTime &&
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 586)
            totalSupply[_id] < pooledCLConstants[_id].minBorrowAmount
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 683)
                require(pooledCLConstants[id].areTokensTransferable, 'T4');
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 356)
        pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_sharesBorrowed);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 371)
        pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.add(_sharesRepaid);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 439)
        pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesToWithdraw);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 465)
        uint256 _borrowerInterestShares = pooledCLVariables[_id].borrowerInterestShares;
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 563)
            pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesWithdrawable);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 649)
            pooledCLVariables[_id].collateralHeld = pooledCLVariables[_id].collateralHeld.sub(_lenderCollateralShare);
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 710)
        uint256 borrowerInterestOnTransferAmount = pooledCLVariables[id].lenders[from].borrowerInterestSharesWithdrawn.mul(amount).div(
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 677)
                totalSupply[id] = totalSupply[id].add(amount);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 644)
        require(IStrategyRegistry(strategyRegistry).registry(_request.collateralAssetStrategy) != 0, 'R6');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 653)
        require(IVerification(verification).verifiers(_request.lenderVerifier), 'R14');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 392)
        require(isWithinLimits(_poolsizeInUSD, _borrowLimitMin, borrowLimitLimits.max), 'ILB1');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 406)
        require(!(borrowLimitLimits.min == _min && borrowLimitLimits.max == _max), 'UBLL2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 418)
        require(!(idealCollateralRatioLimits.min == _min && idealCollateralRatioLimits.max == _max), 'UICRL2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 647)
        require(isWithinLimits(_request.collateralRatio, idealCollateralRatioLimits.min, idealCollateralRatioLimits.max), 'R9');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 430)
        require(!(borrowRateLimits.min == _min && borrowRateLimits.max == _max), 'UBRL2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 646)
        require(isWithinLimits(_request.borrowRate, borrowRateLimits.min, borrowRateLimits.max), 'R8');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 442)
        require(!(collectionPeriodLimits.min == _min && collectionPeriodLimits.max == _max), 'UCPL2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 648)
        require(isWithinLimits(_request.collectionPeriod, collectionPeriodLimits.min, collectionPeriodLimits.max), 'R10');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 454)
        require(!(durationLimits.min == _min && durationLimits.max == _max), 'UDL2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 649)
        require(isWithinLimits(_request.duration, durationLimits.min, durationLimits.max), 'R11');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 466)
        require(!(defaultGracePeriodLimits.min == _min && defaultGracePeriodLimits.max == _max), 'UDGPL2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 650)
        require(isWithinLimits(_request.defaultGracePeriod, defaultGracePeriodLimits.min, defaultGracePeriodLimits.max), 'R12');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 478)
        require(!(gracePenaltyRateLimits.min == _min && gracePenaltyRateLimits.max == _max), 'UGPRL2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 651)
        require(isWithinLimits(_request.gracePenaltyRate, gracePenaltyRateLimits.min, gracePenaltyRateLimits.max), 'R13');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 759)
        depositedCollateralInShares[_id] = depositedCollateralInShares[_id].add(_sharesDeposited);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 846)
        depositedCollateralInShares[_id] = depositedCollateralInShares[_id].sub(_amountInShares);
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 722)
        pooledCreditLineVariables[_id].status = PooledCreditLineStatus.ACTIVE;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 982)
        uint256 _currentPrincipal = pooledCreditLineVariables[_id].principal;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1042)
        uint256 _principal = pooledCreditLineVariables[_id].principal;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1063)
            pooledCreditLineVariables[_id].totalInterestRepaid
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1100)
        pooledCreditLineVariables[_id].status = PooledCreditLineStatus.LIQUIDATED;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1132)
        require(pooledCreditLineVariables[_id].principal == 0, 'C2');
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1203)
            pooledCreditLineVariables[_id].status = currentStatus;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1226)
        pooledCreditLineVariables[_id].lastPrincipalUpdateTime = block.timestamp;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 747)
        address _strategy = pooledCreditLineConstants[_id].collateralAssetStrategy;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 817)
            pooledCreditLineConstants[_id].borrowAsset
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 865)
        address _strategy = pooledCreditLineConstants[_id].collateralAssetStrategy;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 875)
        address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 901)
        address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 934)
            pooledCreditLineConstants[_id].borrowAsset
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1008)
            pooledCreditLineConstants[_id].borrowAsset
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1022)
        address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1041)
        uint256 _penaltyRate = pooledCreditLineConstants[_id].gracePenaltyRate;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1087)
            currentCollateralRatio < pooledCreditLineConstants[_id].idealCollateralRatio ||
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1117)
        address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1240)
            pooledCreditLineConstants[_id].borrowAsset

Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead

When using elements that are smaller than 32 bytes, your contractโ€™s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.

https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed

  1. File: contracts/Verification/twitterVerifier.sol (line 117)
        uint8 _v,
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 164)
        uint128 borrowLimit;
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 165)
        uint128 borrowRate;

Functions guaranteed to revert when called by normal users can be marked payable

If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided.

  1. File: contracts/Verification/twitterVerifier.sol (line 171)
    function unregisterUser(address _user) external onlyOwner {
  1. File: contracts/Verification/twitterVerifier.sol (line 189)
    function updateVerification(address _verification) external onlyOwner {
  1. File: contracts/Verification/twitterVerifier.sol (line 203)
    function updateSignerAddress(address _signerAddress) external onlyOwner {
  1. File: contracts/Verification/twitterVerifier.sol (line 217)
    function updateSignValidity(uint256 _signValidity) external onlyOwner {
  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 247-256)
    function create(
        uint256 _id,
        address _lenderVerifier,
        address _borrowAsset,
        address _borrowAssetStrategy,
        uint256 _borrowLimit,
        uint256 _minBorrowAmount,
        uint256 _collectionPeriod,
        bool _areTokensTransferable
    ) external onlyPooledCreditLine nonReentrant override {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 355)
    function borrowed(uint256 _id, uint256 _sharesBorrowed) external override onlyPooledCreditLine nonReentrant {
  1. File: contracts/PooledCreditLine/LenderPool.sol (lines 366-370)
    function repaid(
        uint256 _id,
        uint256 _sharesRepaid,
        uint256 _interestShares
    ) external override onlyPooledCreditLine nonReentrant {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 380)
    function requestCancelled(uint256 _id) external override onlyPooledCreditLine {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 394)
    function terminate(uint256 _id, address _to) external override onlyPooledCreditLine nonReentrant {
  1. File: contracts/PooledCreditLine/LenderPool.sol (line 752)
    function updateStartFeeFraction(uint256 _startFeeFraction) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 404)
    function updateBorrowLimitLimits(uint256 _min, uint256 _max) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 416)
    function updateIdealCollateralRatioLimits(uint256 _min, uint256 _max) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 428)
    function updateBorrowRateLimits(uint256 _min, uint256 _max) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 440)
    function updateCollectionPeriodLimits(uint256 _min, uint256 _max) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 452)
    function updateDurationLimits(uint256 _min, uint256 _max) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 464)
    function updateDefaultGracePeriodLimits(uint256 _min, uint256 _max) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 476)
    function updateGracePenaltyRateLimits(uint256 _min, uint256 _max) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 492)
    function updatePriceOracle(address _priceOracle) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 508)
    function updateSavingsAccount(address _savingsAccount) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 524)
    function updateProtocolFeeFraction(uint256 _protocolFeeFraction) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 540)
    function updateProtocolFeeCollector(address _protocolFeeCollector) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 556)
    function updateStrategyRegistry(address _strategyRegistry) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 572)
    function updateVerification(address _verification) external onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 720)
    function accept(uint256 _id, uint256 _amount) external nonReentrant override onlyLenderPool {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (lines 772-776)
    function withdrawCollateral(
        uint256 _id,
        uint256 _amount,
        bool _toSavingsAccount
    ) external nonReentrant onlyCreditLineBorrower(_id) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 791)
    function withdrawCollateral(uint256 _id, bool _toSavingsAccount) external nonReentrant onlyCreditLineBorrower(_id) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 893)
    function borrow(uint256 _id, uint256 _amount) external nonReentrant onlyCreditLineBorrower(_id) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1077)
    function liquidate(uint256 _id) external override nonReentrant onlyLenderPool returns (address, uint256) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1130)
    function close(uint256 _id) external nonReentrant onlyCreditLineBorrower(_id) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1143)
    function cancelRequest(uint256 _id) external nonReentrant onlyCreditLineBorrower(_id) {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1158)
    function terminate(uint256 _id) external nonReentrant onlyOwner {
  1. File: contracts/PooledCreditLine/PooledCreditLine.sol (line 1172)
    function cancelRequestOnLowCollection(uint256 _id) external nonReentrant override onlyLenderPool {

#0 - ritik99

2022-04-12T19:03:02Z

All suggestions are valid and the report is highly detailed.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax ยฉ 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter