#47008 [SC-High] any users with expired loan(not settled) can take theft of lenders collateral when the collateral price increase
Description
Brief/Intro
Vulnerability Details
function createSettlement(
string memory _settlementId,
SettleInfo calldata _settleInfo,
string[] memory _loanIds,
LoanInfo[] calldata _loans,
bytes calldata _signature
) external nonReentrant {
// // Verify signature
bytes32 digest = _getSettlementHash(_settlementId, _settleInfo, _loanIds, _loans);
if (!SignatureChecker.isValidSignatureNow(_operator, digest, _signature)) {
revert InvalidSignature();
}
bytes32 settlementId = _settlementId.toBytes32();
if (settlements[settlementId].taker != address(0)) {
revert SettlementAlreadyExists(settlementId);
}
if (_settleInfo.expiryTime < block.timestamp) {
revert SettlementExpired(block.timestamp, _settleInfo.expiryTime);
}
if (_settleInfo.taker != msg.sender) {
revert TakerNotMatched(settlementId, _settleInfo.taker, msg.sender);
}
if (_loans.length == 0) {
revert EmptyLoan();
}
uint256 totalCollateralAmt;
uint256 totalDebtAmt;
address debtToken = _loans[0].debtTokenAddr;
address collateralToken = _loans[0].collateralTokenAddr;
for (uint256 i = 0; i < _loanIds.length; i++) {
bytes32 loanId = _loanIds[i].toBytes32();
LoanInfo memory loan = _loans[i];
if (loans[loanId].maker != address(0)) {
revert LoanAlreadyExisted(loanId);
}
loan.settlementId = settlementId;
loan.settled = false;
loans[loanId] = loan;
totalCollateralAmt += loan.debtData.collateralAmt;
totalDebtAmt += loan.debtData.debtAmt;
if (_settleInfo.takerType == TakerType.BORROW && loan.collateralTokenAddr != collateralToken) {
revert TakerNotMatched(loanId, collateralToken, loan.collateralTokenAddr);
} else if (_settleInfo.takerType == TakerType.LEND && loan.debtTokenAddr != debtToken) {
revert TakerNotMatched(loanId, debtToken, loan.debtTokenAddr);
}
}
if (_settleInfo.takerType == TakerType.LEND) {
uint256 allowance = IERC20(collateralToken).allowance(msg.sender, address(this));
if (allowance < Constants.ALLOWANCE_SCALE * totalCollateralAmt) {
revert TokenAllowanceInsufficient(allowance, Constants.ALLOWANCE_SCALE * totalCollateralAmt);
}
allowance = IERC20(debtToken).allowance(msg.sender, address(this));
if (allowance < totalDebtAmt) {
revert TokenAllowanceInsufficient(allowance, totalDebtAmt);
}
} else {
uint256 allowance = IERC20(collateralToken).allowance(msg.sender, address(this));
if (allowance < totalCollateralAmt) {
revert TokenAllowanceInsufficient(allowance, totalCollateralAmt);
}
}
settlements[settlementId] = _settleInfo;
emit SettlementCreated(msg.sender, settlementId);
}
function addCollateralBeforeSettle(string memory _loanId, uint256 addedAmount) public nonReentrant {
bytes32 loanId = _loanId.toBytes32();
LoanInfo memory loanInfo = loans[loanId];
if (loanInfo.maker == address(0)) {
revert LoanNotFound(loanId);
}
if (loanInfo.settled) {
revert LoanAlreadySettled(loanId);
}
loanInfo.addCollateral(addedAmount);
if (settlements[loanInfo.settlementId].takerType == TakerType.BORROW) {
uint256 allowance = IERC20(loanInfo.collateralTokenAddr).allowance(msg.sender, address(this));
if (allowance < loanInfo.debtData.collateralAmt) {
revert TokenAllowanceInsufficient(allowance, loanInfo.debtData.collateralAmt);
}
}
loans[loanId] = loanInfo;
emit CollateralAdded(msg.sender, loanId, addedAmount);
}
Impact Details
Recommend
Proof of Concept
Proof of Concept
Previous#46893 [SC-High] settlement functionality can be break forever and blocking settlement actions.Next#47009 [SC-Low] Any position can be closed (by repaying the debt) even after the maturity date has passed
Was this helpful?