Rapid Walnut Wasp
Medium
Looking at the documentation quote: "Users can borrow against their NUMA holdings to access rETH
and stay liquid—interest-free and no fees." Lending & Leverage Borrowers will incur unintended interest charges when borrowing against their NUMA
holdings.
It arises from the code implementation in CToken.so
l: the borrowFreshNoTransfer
function applies interest to all loans through:
accountBorrows[borrower].interestIndex = borrowIndex;
wich creates a critical mismatch between promised and actual functionality
https://github.com/sherlock-audit/2024-12-numa-audit/blob/ae1d7781efb4cb2c3a40c642887ddadeecabb97d/Numa/contracts/lending/CToken.sol#L741 The code enforces interest on all loans, breaking a core documented feature of "interest-free loans against NUMA holdings".
function borrowFreshNoTransfer(
address payable borrower,
uint borrowAmount
) internal virtual {
/* Fail if borrow not allowed */
uint allowed = comptroller.borrowAllowed(
address(this),
borrower,
borrowAmount
);
if (allowed != 0) {
revert BorrowComptrollerRejection(allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != getBlockNumber()) {
revert BorrowFreshnessCheck();
}
/* Fail gracefully if protocol has insufficient underlying cash */
if (getCashPrior() < borrowAmount) {
revert BorrowCashNotAvailable();
}
/*
* We calculate the new borrower and total borrow balances, failing on overflow:
* accountBorrowNew = accountBorrow + borrowAmount
* totalBorrowsNew = totalBorrows + borrowAmount
*/
uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower);
uint accountBorrowsNew = accountBorrowsPrev + borrowAmount;
uint totalBorrowsNew = totalBorrows + borrowAmount;
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/*
* We write the previously calculated values into storage.
* Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.
`*/
accountBorrows[borrower].principal = accountBorrowsNew;
accountBorrows[borrower].interestIndex = borrowIndex;
totalBorrows = totalBorrowsNew;
/* We emit a Borrow event */
emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);
}
NUMA
holders suffer continuous losses through unexpected interest charges on supposedly interest-free loans. For example, with a 5% APR and a 10 ETH loan, users would lose 0.5 ETH annually in unintended interest charges.
No response
No response