Skip to content

Latest commit

 

History

History
103 lines (85 loc) · 3.67 KB

020.md

File metadata and controls

103 lines (85 loc) · 3.67 KB

J4de

high

commitCollateral can be called any number of times by anyone

Summary

Borrowers can pre-emptively call CollateralManager.sol#commitCollateral to modify the number of collateral before the lender accepts, resulting in almost 0 collateral.

In addition, the attacker can also call commitCollateral to let the borrower despoit a lot of collateral.

Vulnerability Detail

File: TellerV2.sol
 470     function lenderAcceptBid(uint256 _bidId)
 471         external
 472         override
 473         pendingBid(_bidId, "lenderAcceptBid")
 474         whenNotPaused
 475         returns (
 476             uint256 amountToProtocol,
 477             uint256 amountToMarketplace,
 478             uint256 amountToBorrower
 479         )
 480     {
 481         // Retrieve bid
 482         Bid storage bid = bids[_bidId];
 483
 484         address sender = _msgSenderForMarket(bid.marketplaceId);
 485
 486         (bool isVerified, ) = marketRegistry.isVerifiedLender(
 487             bid.marketplaceId,
 488             sender
 489         );
 490         require(isVerified, "Not verified lender");
 491
 492         require(
 493             !marketRegistry.isMarketClosed(bid.marketplaceId),
 494             "Market is closed"
 495         );
 496
 497         require(!isLoanExpired(_bidId), "Bid has expired");
 498
 499         // Set timestamp
 500         bid.loanDetails.acceptedTimestamp = uint32(block.timestamp);
 501         bid.loanDetails.lastRepaidTimestamp = uint32(block.timestamp);
 502
 503         // Mark borrower's request as accepted
 504         bid.state = BidState.ACCEPTED;
 505
 506         // Declare the bid acceptor as the lender of the bid
 507         bid.lender = sender;
 508
 509         // Tell the collateral manager to deploy the escrow and pull funds from the borrower if applicable
 510  >>     collateralManager.deployAndDeposit(_bidId);
 511
 512         // Transfer funds to borrower from the lender
 513         amountToProtocol = bid.loanDetails.principal.percent(protocolFee());
 514         amountToMarketplace = bid.loanDetails.principal.percent(
 515             marketRegistry.getMarketplaceFee(bid.marketplaceId)
 516         );

Lenders are more inclined to lend loans to borrowers with a lot of collaterals. When a lender accepts a bid with a lot of collaterals, it will call the lenderAcceptBid function, and the lenderAcceptBid function will further call collateralManager.deployAndDeposit to allow the borrower to deposit collaterals.

File: CollateralManager.sol
119     function commitCollateral(
120         uint256 _bidId,
121         Collateral[] calldata _collateralInfo
122     ) public returns (bool validation_) {
123         address borrower = tellerV2.getLoanBorrower(_bidId);
124         (validation_, ) = checkBalances(borrower, _collateralInfo);
125
126         //if the collateral info is valid, call commitCollateral for each one
127         if (validation_) {
128             for (uint256 i; i < _collateralInfo.length; i++) {
129                 Collateral memory info = _collateralInfo[i];
130                 _commitCollateral(_bidId, info);
131             }
132         }
133     }

Borrowers can call commitCollateral in advance to modify the number of collateral to 0, and then they can borrow at zero cost.

Impact

Borrowers can borrow with zero collateral, and they don’t have to repay at all.

Code Snippet

https://github.com/teller-protocol/teller-protocol-v2/blob/cb66c9e348cdf1fd6d9b0416a49d663f5b6a693c/packages/contracts/contracts/CollateralManager.sol#L117-L130

Tool used

Manual Review

Recommendation

It is recommended that commitCollateral can only be called once and add onlyTellerV2.