Beedle: function-level review of top-1 misses

September 19, 2026 ยท View on GitHub

Run regenerated from cache (bench/run_bench.py beedle, category resolution, locate threshold 0.5). An issue is scored on one function ranking: its true (file, question) pair with the highest file-level p, as in run_bench.py. 34 issues were located; in 14 the #1-ranked function is one the judges named. The 20 others are below.

Rule: the #1 function counts when it is on the finding's exploit chain: it calls a judged function, is called by one, produces the value the bug corrupts, or is where that value is consumed. Sharing pool or loan state with the judged function is not enough.

Strict: 14 of 34. Counting on-chain functions: 18 of 34.

IdJudged fn#1 fn (p)#2, #3 (p)VerdictPath
H-2repayrefinance (0.84)seizeLoan (0.82), setPool (0.79)not on the chainThe re-entrancy is repay's collateral transfer before delete loans[loanId]; refinance neither calls nor is called by repay.
H-3setPoolrefinance (0.84)seizeLoan (0.82), setPool (0.79)not on the chainThe re-entrancy is setPool's refund transfer before pools[poolId] = p; refinance never calls setPool (only zapBuyLoan does).
H-5refinancerepay (0.93)giveLoan (0.89), seizeLoan (0.89)not on the chainThe attack is startAuction then refinance/giveLoan resetting auctionStartTimestamp; repay plays no part.
H-7buyLoanrepay (0.93)giveLoan (0.89), seizeLoan (0.89)not on the chainBorrower pushes a high-LTV loan into another pool through buyLoan's missing ratio check; repay is not involved.
H-9buyLoanrepay (0.93)giveLoan (0.89), seizeLoan (0.89)not on the chainFake pool with mismatched tokens passed to buyLoan, then the loan is seized; repay is not involved.
H-11buyLoanrepay (0.93)giveLoan (0.89), seizeLoan (0.89)not on the chainTheft runs setPool (fake pool), buyLoan, borrow, startAuction, seizeLoan. The report notes repay then reverts for the victim, a side effect, not the exploit.
H-13update, sellProfitswithdraw (0.69)claim (0.69), update (0.62)on the chainwithdraw calls updateFor, which calls update: the lazy index is computed there and settled into claimable for the withdrawing staker.
H-19buyLoanrepay (0.93)giveLoan (0.89), seizeLoan (0.89)not on the chainAttack runs updateMaxLoanRatio, refinance, startAuction front-running a victim's buyLoan; repay is not involved.
H-21giveLoanrefinance (0.84)giveLoan (0.78), repay (0.74)not on the chainInterest is capitalised into debt inside giveLoan; refinance has its own, separate debt update.
H-23borrow, setPoolbuyLoan (0.69)refinance (0.64), giveLoan (0.56)not on the chainSandwich is setPool, victim borrow, then startAuction/seizeLoan; buyLoan is not involved.
H-24update, updateFor, depositwithdraw (0.69)claim (0.69), update (0.62)on the chainwithdraw calls the judged updateFor and update, the functions that fold pre-stake WETH into index with no holder.
H-25claimwithdraw (0.69)claim (0.69), update (0.62)not on the chainclaim overwrites balance; the loss lands in update's _diff. withdraw only calls update and neither calls nor is called by claim.
H-26borrow, refinancebuyLoan (0.69)refinance (0.64), giveLoan (0.56)not on the chainLender front-runs borrow/refinance with setPool (short auctionLength), then startAuction/seizeLoan; buyLoan is not involved.
K-27borrow, refinancebuyLoan (0.69)refinance (0.64), giveLoan (0.56)not on the chainDuplicate of H-26; same path, no buyLoan.
M-1_calculateInterest, giveLoanrefinance (0.81)giveLoan (0.78), borrow (0.73)on the chainrefinance calls the judged _calculateInterest and consumes its truncated interest. The report's impact lands in giveLoan's ratio check, so this is the weakest of the four.
M-2borrow, refinancebuyLoan (0.69)refinance (0.64), giveLoan (0.56)not on the chainLender front-runs borrow/refinance with setPool/updateInterestRate; buyLoan is not involved.
M-5giveLoanrepay (0.93)giveLoan (0.89), seizeLoan (0.89)not on the chainLender calls giveLoan during an auction to cancel it and block buyLoan; repay is not involved.
M-7seizeLoanrefinance (0.84)seizeLoan (0.82), setPool (0.79)not on the chainThe re-entrancy is seizeLoan's collateral transfer before delete loans[loanId]; refinance is not involved.
M-13_calculateInterestrefinance (0.81)giveLoan (0.78), borrow (0.73)on the chainrefinance calls _calculateInterest and settles the loan with debtToPay = debt + interest, so zero-truncated interest lets the borrower roll the loan without paying interest.
M-14borrow, repayseizeLoan (0.84)repay (0.77), refinance (0.69)not on the chainWith borrowerFee = 0 the attacker borrows and repays pool liquidity for free around victims; seizeLoan only reads borrowerFee for its gov fee.

Close call: H-11. repay is where the corrupted loan.lender is consumed (it reverts), but that is a side effect, not the collateral theft, so it is not counted.