Rapid Walnut Wasp
High
The Numa
protocol has a critical race condition vulnerability between repayBorrowFresh
and liquidateBorrowFresh
transactions that can lead to double payment scenarios.
The issue arises when a borrower sends a transaction to repay their debt position when it becomes liquidatable
, but a liquidateBorrowFresh
transaction is executed just before the user's repayBorrowFresh
transaction.
The main entry points that can lead to this race condition are:
repayBorrowInternal() - Called by users directly repaying their loans repayBorrowBehalfInternal() - Called by third parties repaying on behalf of borrowers liquidateBorrowInternal() - Called by liquidators
// In CToken.sol
function liquidateBorrowFresh(...) {
// First repayment happens here
uint actualRepayAmount = repayBorrowFresh(liquidator, borrower, repayAmount);
// Seizes collateral
require(cTokenCollateral.seize(liquidator, borrower, seizeTokens) == NO_ERROR, "token seizure failed");
}
function repayBorrowFresh(...) {
// Second repayment happens here
uint accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;
accountBorrows[borrower].principal = accountBorrowsNew;
}
All these functions ultimately flow through to repayBorrowFresh
, which handles the actual debt reduction logic. The critical path occurs in liquidateBorrowFresh
where it calls repayBorrowFresh
internally before seizing collateral. This creates a window where a user's direct repayment transaction could execute after the liquidation has already processed a repayment.
The state changes happen in repayBorrowFresh
where the borrower's debt is reduced:
uint accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;
accountBorrows[borrower].principal = accountBorrowsNew;
If a user's repayBorrowFresh
executes after liquidateBorrowFresh
but before the transaction is mined, they will process another repayment against their already-reduced debt balance. This results in the borrower paying twice - once through the liquidation and once through their direct repayment.
Looking at CToken.sol
, the race condition can occur naturally, legitimate bots running liquidation operations and regular users trying to save their positions will naturally tend to submit transactions around the same time. The race condition emerges from this normal, expected behavior rather than from any malicious exploitation.
No response
No response
The impact is high , as the users ends up paying twice their debt.
No response
No response