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
Rank: 7/24
Findings: 2
Award: $762.33
๐ Selected for report: 1
๐ Solo Findings: 0
420.4341 USDC - $420.43
transfer()
not checkedThe 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.
IERC20(_borrowAsset).transfer(_to, _fee);
approve()
not checkedSAVINGS_ACCOUNT.approve(_borrowAsset, address(POOLED_CREDIT_LINE), type(uint256).max);
IERC20(_collateralAsset).approve(_strategy, _amount);
IERC20(_borrowAsset).approve(_strategy, _amount);
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
.
if (_totalLent.add(_amount) > _maxLent) { _amountToLend = _maxLent.sub(_totalLent); }
address(0x0)
when assigning values to address
state variableslenderPool = _lenderPool;
USDC = _usdc;
All multiplications should be done first, followed by divisions
uint256 _collateralNeeded = _currentDebt .mul(pooledCreditLineConstants[_id].idealCollateralRatio) .div(_ratioOfPrices) .mul(10**_decimals) .div(SCALING_FACTOR);
_maxPossible = _totalCollateralToken.mul(_ratioOfPrices).div(_collateralRatio).mul(SCALING_FACTOR).div(10**_decimals);
_currentCollateralRatio = calculateTotalCollateralTokens(_id).mul(_ratioOfPrices).div(_currentDebt).mul(SCALING_FACTOR).div( 10**_decimals );
* @dev only owner can register users
__gap[50]
storage variable to allow for new storage variables in later versionsSee 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.
contract TwitterVerifier is Initializable, IVerifier, OwnableUpgradeable, EIP712Upgradeable {
contract LenderPool is ERC1155Upgradeable, ReentrancyGuard, OwnableUpgradeable, IPooledCreditLineEnums, ILenderPool {
contract PooledCreditLine is ReentrancyGuard, OwnableUpgradeable, IPooledCreditLine {
safeApprove()
is deprecatedDeprecated in favor of safeIncreaseAllowance()
and safeDecreaseAllowance()
IERC20(_borrowAsset).safeApprove(_strategy, _amount);
public
functions not called by the contract should be declared external
insteadContracts are allowed to override their parents' functions and change the visibility from external
to public
.
function getPrincipal(uint256 _id) public view override returns (uint256) {
nonReentrant
modifier
should occur before all other modifiersThis is a best-practice to protect against reentrancy in other modifiers
) external onlyPooledCreditLine nonReentrant override {
function borrowed(uint256 _id, uint256 _sharesBorrowed) external override onlyPooledCreditLine nonReentrant {
) external override onlyPooledCreditLine nonReentrant {
function terminate(uint256 _id, address _to) external override onlyPooledCreditLine nonReentrant {
@return
* @param _lender lender whose share of prinipal is to be withdrawn */ function calculatePrincipalWithdrawable(uint256 _id, address _lender) external returns (uint256) {
* @param _lender address of the lender for which query is made */ function getLenderInfo(uint256 _id, address _lender) external view returns (LenderInfo memory) {
* @param _id identifier for the pooled credit line */ function liquidate(uint256 _id) external override nonReentrant onlyLenderPool returns (address, uint256) {
* @param _id identifier for the pooled credit line */ function getPrincipal(uint256 _id) public view override returns (uint256) {
/// @param _name name of the verifier (used in domain seperator)
seperator
//-------------------------------- Global varibales start --------------------------------//
varibales
* @param borrowerInterestSharesWithdrawn interest paid by borroower in shares, withdrawn by lender
borroower
* @param borrowLimit max tokens that was reqeuested by borrower
reqeuested
* @param id idenitifer for the pooled credit line
idenitifer
* @notice Emitted when liqudity provided by lender is withdrawn as pool is cancelled
liqudity
* @param shares shares withdrawn by lender from interest accured by yield as well as supplied by borrower
accured
//--------------------------- Globa var update events start ---------------------------//
Globa
* @dev lent amount is deposited to savings account only once borrow limit is reached or if start is callled
callled
* @param _to address to which all the borrow tokens are transfered
transfered
* @param _lender lender whose share of prinipal is to be withdrawn
prinipal
* @notice Function used to liquidate a pooleed credit line
pooleed
* @notice emitted when threhsolds for one of the parameters is updated
threhsolds
* @notice emitted when the pooled credit line is terminatd by owner
terminatd
if(_totalLent.sub(_fee) < pooledCLConstants[_id].minBorrowAmount) {
if(
-> if (
indexed
fieldsEach event
should use three indexed
fields if there are three or more fields
event SignValidityUpdated(uint256 signValidity);
event Lend(uint256 indexed id, address indexed user, uint256 amount);
event WithdrawLiquidity(uint256 indexed id, address indexed user, uint256 shares);
event WithdrawLiquidityOnCancel(uint256 indexed id, address indexed user, uint256 amount);
event InterestWithdrawn(uint256 indexed id, address indexed user, uint256 shares);
event LiquidationWithdrawn(uint256 indexed id, address indexed user, uint256 collateralShare);
event Liquidated(uint256 indexed id, uint256 collateralLiquidated);
event StartFeeFractionUpdated(uint256 updatedStartFeeFraction);
event LimitsUpdated(string indexed limitType, uint256 max, uint256 min);
event ProtocolFeeFractionUpdated(uint256 updatedProtocolFee);
event CollateralDeposited(uint256 indexed id, uint256 amount, address indexed strategy);
event CollateralWithdrawn(uint256 indexed id, uint256 amount);
event BorrowedFromPooledCreditLine(uint256 indexed id, uint256 borrowAmount);
event PooledCreditLineAccepted(uint256 indexed id, uint256 amount);
event PartialPooledCreditLineRepaid(uint256 indexed id, address indexed repayer, uint256 repayAmount);
event CompletePooledCreditLineRepaid(uint256 indexed id, address indexed repayer, uint256 repayAmount);
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
341.9032 USDC - $341.90
/** * @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;
/** * @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
-loopsfor (uint256 i; i < ids.length; ++i) {
<array>.length
should not be looked up in every loop of a for
-loopEven memory arrays incur the overhead of bit tests and bit shifts to calculate the array length
for (uint256 i; i < ids.length; ++i) {
calldata
instead of memory
for read-only arguments in external
functions saves gasstring memory _name,
string memory _version
string memory _twitterId,
string memory _tweetId,
internal
functions only called once can be inlined to save gasfunction _rebalanceInterestWithdrawn( uint256 id, uint256 amount, address from, address to
function _limitBorrowedInUSD(address _borrowToken, uint256 _borrowLimit, uint256 _minBorrowAmount) internal view {
function _createRequest(Request calldata _request) internal returns (uint256) {
function _notifyRequest( uint256 _id, address _lenderVerifier, address _borrowToken, address _borrowAssetStrategy, uint256 _borrowLimit, uint256 _minBorrowedAmount, uint256 _collectionPeriod, bool _areTokensTransferable
function _borrow(uint256 _id, uint256 _amount) internal {
function _withdrawBorrowAmount( address _asset, address _strategy, uint256 _amountInTokens ) internal returns (uint256) {
function _repay(uint256 _id, uint256 _amount) internal returns (uint256) {
function updateStateOnPrincipalChange(uint256 _id, uint256 _updatedPrincipal) internal {
if
-statements with mutually-exclusive conditions should be changed to if
-else
statementsIf two conditions are the same, their blocks should be combined
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 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
pragma solidity 0.7.6;
pragma solidity 0.7.6;
pragma solidity 0.7.6;
require()
statements that use &&
saves gasSee this issue for an example
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 functionrequire(_minBorrowAmount <= _borrowLimit, 'ILB2');
require(_amount <= _withdrawableCollateral, 'WC1');
require(_amount <= calculateBorrowableAmount(_id), 'B3');
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.
emit SignerUpdated(signerAddress);
SAVINGS_ACCOUNT.approve(_borrowAsset, address(POOLED_CREDIT_LINE), type(uint256).max);
SAVINGS_ACCOUNT.approve(_borrowAsset, address(POOLED_CREDIT_LINE), type(uint256).max);
pooledCLConstants[_id].borrowAsset = _borrowAsset;
require(block.timestamp < pooledCLConstants[_id].startTime, 'L2');
address _borrowAsset = pooledCLConstants[_id].borrowAsset;
address _strategy = pooledCLConstants[_id].borrowAssetStrategy;
address _borrowAsset = pooledCLConstants[_id].borrowAsset;
address _borrowAsset = pooledCLConstants[_id].borrowAsset;
block.timestamp > pooledCLConstants[_id].startTime &&
totalSupply[_id] < pooledCLConstants[_id].minBorrowAmount
require(pooledCLConstants[id].areTokensTransferable, 'T4');
pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_sharesBorrowed);
pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.add(_sharesRepaid);
pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesToWithdraw);
uint256 _borrowerInterestShares = pooledCLVariables[_id].borrowerInterestShares;
pooledCLVariables[_id].sharesHeld = pooledCLVariables[_id].sharesHeld.sub(_interestSharesWithdrawable);
pooledCLVariables[_id].collateralHeld = pooledCLVariables[_id].collateralHeld.sub(_lenderCollateralShare);
uint256 borrowerInterestOnTransferAmount = pooledCLVariables[id].lenders[from].borrowerInterestSharesWithdrawn.mul(amount).div(
totalSupply[id] = totalSupply[id].add(amount);
require(IStrategyRegistry(strategyRegistry).registry(_request.collateralAssetStrategy) != 0, 'R6');
require(IVerification(verification).verifiers(_request.lenderVerifier), 'R14');
require(isWithinLimits(_poolsizeInUSD, _borrowLimitMin, borrowLimitLimits.max), 'ILB1');
require(!(borrowLimitLimits.min == _min && borrowLimitLimits.max == _max), 'UBLL2');
require(!(idealCollateralRatioLimits.min == _min && idealCollateralRatioLimits.max == _max), 'UICRL2');
require(isWithinLimits(_request.collateralRatio, idealCollateralRatioLimits.min, idealCollateralRatioLimits.max), 'R9');
require(!(borrowRateLimits.min == _min && borrowRateLimits.max == _max), 'UBRL2');
require(isWithinLimits(_request.borrowRate, borrowRateLimits.min, borrowRateLimits.max), 'R8');
require(!(collectionPeriodLimits.min == _min && collectionPeriodLimits.max == _max), 'UCPL2');
require(isWithinLimits(_request.collectionPeriod, collectionPeriodLimits.min, collectionPeriodLimits.max), 'R10');
require(!(durationLimits.min == _min && durationLimits.max == _max), 'UDL2');
require(isWithinLimits(_request.duration, durationLimits.min, durationLimits.max), 'R11');
require(!(defaultGracePeriodLimits.min == _min && defaultGracePeriodLimits.max == _max), 'UDGPL2');
require(isWithinLimits(_request.defaultGracePeriod, defaultGracePeriodLimits.min, defaultGracePeriodLimits.max), 'R12');
require(!(gracePenaltyRateLimits.min == _min && gracePenaltyRateLimits.max == _max), 'UGPRL2');
require(isWithinLimits(_request.gracePenaltyRate, gracePenaltyRateLimits.min, gracePenaltyRateLimits.max), 'R13');
depositedCollateralInShares[_id] = depositedCollateralInShares[_id].add(_sharesDeposited);
depositedCollateralInShares[_id] = depositedCollateralInShares[_id].sub(_amountInShares);
pooledCreditLineVariables[_id].status = PooledCreditLineStatus.ACTIVE;
uint256 _currentPrincipal = pooledCreditLineVariables[_id].principal;
uint256 _principal = pooledCreditLineVariables[_id].principal;
pooledCreditLineVariables[_id].totalInterestRepaid
pooledCreditLineVariables[_id].status = PooledCreditLineStatus.LIQUIDATED;
require(pooledCreditLineVariables[_id].principal == 0, 'C2');
pooledCreditLineVariables[_id].status = currentStatus;
pooledCreditLineVariables[_id].lastPrincipalUpdateTime = block.timestamp;
address _strategy = pooledCreditLineConstants[_id].collateralAssetStrategy;
pooledCreditLineConstants[_id].borrowAsset
address _strategy = pooledCreditLineConstants[_id].collateralAssetStrategy;
address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
pooledCreditLineConstants[_id].borrowAsset
pooledCreditLineConstants[_id].borrowAsset
address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
uint256 _penaltyRate = pooledCreditLineConstants[_id].gracePenaltyRate;
currentCollateralRatio < pooledCreditLineConstants[_id].idealCollateralRatio ||
address _borrowAsset = pooledCreditLineConstants[_id].borrowAsset;
pooledCreditLineConstants[_id].borrowAsset
uints
/ints
smaller than 32 bytes (256 bits) incurs overheadWhen 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
uint8 _v,
uint128 borrowLimit;
uint128 borrowRate;
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.
function unregisterUser(address _user) external onlyOwner {
function updateVerification(address _verification) external onlyOwner {
function updateSignerAddress(address _signerAddress) external onlyOwner {
function updateSignValidity(uint256 _signValidity) external onlyOwner {
function create( uint256 _id, address _lenderVerifier, address _borrowAsset, address _borrowAssetStrategy, uint256 _borrowLimit, uint256 _minBorrowAmount, uint256 _collectionPeriod, bool _areTokensTransferable ) external onlyPooledCreditLine nonReentrant override {
function borrowed(uint256 _id, uint256 _sharesBorrowed) external override onlyPooledCreditLine nonReentrant {
function repaid( uint256 _id, uint256 _sharesRepaid, uint256 _interestShares ) external override onlyPooledCreditLine nonReentrant {
function requestCancelled(uint256 _id) external override onlyPooledCreditLine {
function terminate(uint256 _id, address _to) external override onlyPooledCreditLine nonReentrant {
function updateStartFeeFraction(uint256 _startFeeFraction) external onlyOwner {
function updateBorrowLimitLimits(uint256 _min, uint256 _max) external onlyOwner {
function updateIdealCollateralRatioLimits(uint256 _min, uint256 _max) external onlyOwner {
function updateBorrowRateLimits(uint256 _min, uint256 _max) external onlyOwner {
function updateCollectionPeriodLimits(uint256 _min, uint256 _max) external onlyOwner {
function updateDurationLimits(uint256 _min, uint256 _max) external onlyOwner {
function updateDefaultGracePeriodLimits(uint256 _min, uint256 _max) external onlyOwner {
function updateGracePenaltyRateLimits(uint256 _min, uint256 _max) external onlyOwner {
function updatePriceOracle(address _priceOracle) external onlyOwner {
function updateSavingsAccount(address _savingsAccount) external onlyOwner {
function updateProtocolFeeFraction(uint256 _protocolFeeFraction) external onlyOwner {
function updateProtocolFeeCollector(address _protocolFeeCollector) external onlyOwner {
function updateStrategyRegistry(address _strategyRegistry) external onlyOwner {
function updateVerification(address _verification) external onlyOwner {
function accept(uint256 _id, uint256 _amount) external nonReentrant override onlyLenderPool {
function withdrawCollateral( uint256 _id, uint256 _amount, bool _toSavingsAccount ) external nonReentrant onlyCreditLineBorrower(_id) {
function withdrawCollateral(uint256 _id, bool _toSavingsAccount) external nonReentrant onlyCreditLineBorrower(_id) {
function borrow(uint256 _id, uint256 _amount) external nonReentrant onlyCreditLineBorrower(_id) {
function liquidate(uint256 _id) external override nonReentrant onlyLenderPool returns (address, uint256) {
function close(uint256 _id) external nonReentrant onlyCreditLineBorrower(_id) {
function cancelRequest(uint256 _id) external nonReentrant onlyCreditLineBorrower(_id) {
function terminate(uint256 _id) external nonReentrant onlyOwner {
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.