#47115 [SC-Critical] Missing Settlement Status Validation in Loan Operations
Submitted on Jun 9th 2025 at 02:57:53 UTC by @Catchme for IOP | Term Structure Institutional
Report ID: #47115
Report Type: Smart Contract
Report severity: Critical
Target: https://github.com/term-structure/tsi-contract/blob/main/src/Settlement.sol
Impacts:
Protocol insolvency
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief/Intro
Critical settlement status validation is missing in multiple loan operations in the Settlement contract, allowing users to perform operations on unsettled loans. This vulnerability enables attackers to steal funds, manipulate loan states, and bypass the intended settlement process flow, potentially resulting in significant direct financial losses to both lenders and borrowers.
Vulnerability Details
In the Settlement contract's architecture, loans must first be settled through the settle() function before any loan operations can be performed. This function executes the core fund transfers and marks the loan as settled by setting loans[loanId].settled = true. However, several critical loan operations fail to verify this settlement prerequisite:
// Example of missing validation in liquidate() function - lines 335-356
function liquidate(string memory _loanId, uint256 liquidationAmt) external nonReentrant {
bytes32 loanId = _loanId.toBytes32();
LoanInfo memory loanInfo = loans[loanId];
// Missing validation: if (!loanInfo.settled) revert LoanNotSettled(loanId);
(uint256 collateralToLiquidator, uint256 collateralToProtocol) =
loanInfo.liquidate(loanId, _oracle, _minimumDebtValue, liquidationAmt);
// Transfers happen without settlement confirmation
IERC20(loanInfo.debtTokenAddr).safeTransferFrom(msg.sender, loanInfo.lender, liquidationAmt);
IERC20(loanInfo.collateralTokenAddr).safeTransferFrom(loanInfo.lender, msg.sender, collateralToLiquidator);
IERC20(loanInfo.collateralTokenAddr).safeTransferFrom(loanInfo.lender, _feeCollector, collateralToProtocol);
// ...
}The affected functions include:
repay()(line 277)removeCollateral()(line 296)addCollateral()(line 307)liquidate()(line 335)delivery()(line 324)
This contrasts with addCollateralBeforeSettle() and settle() which correctly implement settlement status validation:
Impact Details
This vulnerability creates multiple attack vectors with direct financial impact:
Direct Fund Theft via Operations on Unsettled Loans:
Attackers can call
liquidate()on unsettled loans, extracting collateral tokens from lenders who approved allowances expecting the normal settlement flowUsers can call
addCollateral()on unsettled loans, causing immediate token transfers without loan establishmentBoth scenarios result in immediate and irrecoverable financial loss
Protocol State Corruption:
Premature
repay()calls can manipulate loan parameters on unsettled loansremoveCollateral()can be called before proper collateralization is establishedThese operations break the protocol's accounting system and create inconsistent state
Proof of Concept
POC
Was this helpful?