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…
Chain
Other
Category
untagged
Date
Apr 2024
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
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.
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-registrymirror.
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#
| Impact | HIGH — buyout pays pool lenders via safeTransferFrom but never calls loanLiquidation(), so outstanding/cash accounting stays stale and repaid principal is unclaimable |
| Protocol | Gondi — NFT multi-source lending / pool LoanManager |
| Vulnerable code | AuctionWithBuyoutLoanLiquidator.settleWithBuyout repay loop (no LoanManager hook) |
| Bug class | Missing liquidation accounting callback on buyout path |
| Finding | Code4rena — Gondi, 2024-04 · #35208 · reporter minhquanym |
| Report | code4rena.com/reports/2024-04-gondi |
| Source | AuditVault |
| Status | Audit finding — confirmed; mitigated by adding loanLiquidation call |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
- Gondi Pool implements
LoanManager.loanLiquidationto clear outstanding and credit cash/queues. settleWithBuyouttransfers owed principal to other lenders (including the Pool) and callsloanLiquidatedon the loan contract.- It never calls
loanLiquidationon pool lenders → accounting diverges from token balances. - Depositors cannot withdraw the returned principal (locked / unaccounted).
The vulnerable code#
// 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#
- Depositors fund the Pool; Pool books a junior tranche.
- Multi-tranche auction opens (main lender + Pool junior).
- Main lender
settleWithBuyout— pays Pool its principal from the buyer's wallet. - Pool
balanceOfrises;outstandingandcashAccountingstay stale. - Depositors can only withdraw liquid cashAccounting — repaid principal is locked.
Diagrams#
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#
- AuditVault finding #35208
- Code4rena report 2024-04-gondi
- Reduced from code-423n4/2024-04-gondi@b9863d7
settleWithBuyout+ Pool.sol loanLiquidation
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 35208-h-06-function-settlewithbuyout-does-not-call-loanmanagerloan_exp (evm-hack-registry mirror).
- AuditVault finding: 35208-h-06-function-settlewithbuyout-does-not-call-loanmanagerloan.
Alerts & third-party analyses
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.