Reproduced Exploit

Gondi — settleWithBuyout skips LoanManager.loanLiquidation

1. Gondi Pool implements LoanManager.loanLiquidation to clear outstanding and credit cash/queues. 2. settleWithBuyout transfers owed principal to other lenders (including the Pool) and calls loanLiquidated on the loan contract. 3. It never calls loanLiquidation on pool lenders → accounting diverges…

Apr 2024Otheruntagged3 min read

Chain

Other

Category

untagged

Date

Apr 2024

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 35208-h-06-function-settlewithbuyout-does-not-call-loanmanagerloan. Standalone Foundry PoC and full write-up: 35208-h-06-function-settlewithbuyout-does-not-call-loanmanagerloan_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/liquidation-logic · vuln/accounting · vuln/locked-funds

Reproduction: self-contained Foundry PoC with only forge-std — no fork, no RPC. Full trace: output.txt. PoC: test/35208-h-06-function-settlewithbuyout-does-not-call-loanmanagerloan.sol.


Key info#

ImpactHIGH — buyout pays pool lenders via safeTransferFrom but never calls loanLiquidation(), so outstanding/cash accounting stays stale and repaid principal is unclaimable
ProtocolGondi — NFT multi-source lending / pool LoanManager
Vulnerable codeAuctionWithBuyoutLoanLiquidator.settleWithBuyout repay loop (no LoanManager hook)
Bug classMissing liquidation accounting callback on buyout path
FindingCode4rena — Gondi, 2024-04 · #35208 · reporter minhquanym
Reportcode4rena.com/reports/2024-04-gondi
SourceAuditVault
StatusAudit finding — confirmed; mitigated by adding loanLiquidation call
Compiler^0.8.24 (PoC)

TL;DR#

  1. Gondi Pool implements LoanManager.loanLiquidation to clear outstanding and credit cash/queues.
  2. settleWithBuyout transfers owed principal to other lenders (including the Pool) and calls loanLiquidated on the loan contract.
  3. It never calls loanLiquidation on pool lenders → accounting diverges from token balances.
  4. Depositors cannot withdraw the returned principal (locked / unaccounted).

The vulnerable code#

SOLIDITY
// AuctionWithBuyoutLoanLiquidator.settleWithBuyout
for (uint256 i; i < _loan.tranche.length;) {
    if (i != largestTrancheIdx) {
        // ... compute owed ...
        asset.safeTransferFrom(msg.sender, thisTranche.lender, owed);
        // @> VULN: no ILoanManager(lender).loanLiquidation(...)
    }
}
IMultiSourceLoan(_auction.loanAddress).loanLiquidated(_auction.loanId, _loan);
// FIX: for each pool lender, call loanLiquidation with principal/received

Root cause#

Buyout treats every other lender as a passive EOA address that only needs a token transfer. Pool lenders also need the LoanManager callback that updates outstanding principal and getTotalReceived / cash. Without it, tokens sit on the Pool while share accounting still believes the principal is on loan.

Attack walkthrough#

  1. Depositors fund the Pool; Pool books a junior tranche.
  2. Multi-tranche auction opens (main lender + Pool junior).
  3. Main lender settleWithBuyout — pays Pool its principal from the buyer's wallet.
  4. Pool balanceOf rises; outstanding and cashAccounting stay stale.
  5. Depositors can only withdraw liquid cashAccounting — repaid principal is locked.

Diagrams#

sequenceDiagram participant Main as MainLender participant House as AuctionHouse participant Pool as GondiPool Main->>House: settleWithBuyout Main->>Pool: safeTransferFrom owed principal House->>House: loanLiquidated only Note over Pool: outstanding uncleared<br/>cashAccounting stale Note over Pool: repaid principal locked

Impact#

Pool depositors lose access to principal returned via buyout until (if ever) accounting is manually repaired. High severity accounting break on the liquidation buyout path.

Taxonomy#

  • genome: liquidation-logic, data-corruption/price-manipulation, liquidation-underwater, timestamp-dependence
  • sector: lending, token, vault
  • severity: high
  • platform: code4rena

Sources#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.