Reproduced Exploit
Folks Finance: Missing utilisation-ratio guard: on a fresh pool the attacker pushes totalDebt (1e18) far
Chain
Other
Category
untagged
Date
Jan 1970
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: 61019-infinite-interest-rate-bug-immunefi-folks-finance-git. Standalone Foundry PoC and full write-up: 61019-infinite-interest-rate-bug-immunefi-folks-finance-git_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/theft · vuln/locked-funds · vuln/unfair-mint
Reproduction: a faithful minimal reproduction of the vulnerable finding — the vulnerable function is reproduced verbatim (marked
@>) with faithful minimal doubles; local deploy, no fork.
Root cause#
Missing utilisation-ratio guard: on a fresh pool the attacker pushes totalDebt (1e18) far above totalDeposits (1e5), so calcUtilisationRatio returns 1e31 (>>100%) and the variable borrow rate explodes to ~4e31; after one block the attacker's 1e5-wei deposit over-mints to a ~5.7e23 underlying claim (~5.7e18x the pool's real asset base), letting them drain the entire pool and steal every co-deposito
/// utilisation ratio runs far above 1e18 (100%), exploding every downstream
/// interest rate.
function calcUtilisationRatio(uint256 totalDebt, uint256 totalDeposits) internal pure returns (uint256) {
return totalDeposits > 0 ? totalDebt.mulDiv(ONE_18_DP, totalDeposits) : 0; // @> no `if (totalDebt > totalDeposits) revert RatioExceedsOne();` guard: utilisation exceeds 1e18 when debt > deposits, exploding the borrow/deposit rates
}
Why it's exploitable here#
Missing utilisation-ratio guard: on a fresh pool the attacker pushes totalDebt (1e18) far above totalDeposits (1e5), so calcUtilisationRatio returns 1e31 (>>100%) and the variable borrow rate explodes to ~4e31; after one block the attacker's 1e5-wei deposit over-mints to a ~5.7e23 underlying claim (~5.7e18x the pool's real asset base), letting them drain the entire pool and steal every co-depositor's funds (protocol insolvency + direct theft).
Attack path#
Marked-line walkthrough (Playground)#
The EVM Playground pins each step to the exact executed source line in 0x671d353a77…:
- L72 — Setup: full-precision mulDiv: Setup: assembly in
mulDivcomputes the 512-bit intermediate — precise math that faithfully returns the runaway ratio, not the bug. - L135 — Utilisation ratio has no cap: Root cause:
totalDebt.mulDiv(ONE_18_DP, totalDeposits)is returned uncapped, so debt 1e18 over deposits 1e5 gives a 1e31 ratio (>>100%). - L167 — Stable borrow-rate calc:
calcStableBorrowInterestRateconsumes the uncapped ratio, turning out-of-range utilisation into an absurd rate. - L212 — Deposit-rate calc:
calcDepositInterestRatealso scales off the runaway utilisation, inflating per-block yield on the attacker's tiny deposit. - L304 — Setup: share balance storage: Setup:
balanceOftracks pool shares — the ledger the attacker's over-minted claim gets written into. - L405 — Abstract utilisation-ratio hook:
_utilisationRatiois the virtual hook implemented by the uncapped formula above. - L440 — Call site feeds interest accrual: Here the uncapped
utilisationRatioenters accrual, exploding the borrow rate to ~4e31 and over-minting the attacker's claim after one block.
PoC#
Registry (Foundry, local deploy — verbatim vulnerable source + harm-asserting test + negative control):
cd 61019-infinite-interest-rate-bug-immunefi-folks-finance-git_exp
forge test -vvv
The browser Playground replays the same synthetic opcode-for-opcode and measures the harm: Missing utilisation-ratio guard: on a fresh pool the attacker pushes totalDebt (1e18) far above totalDeposits (1e5), so calcUtilisationRatio. Both gates are green (registry forge test PASS + Playground _verify-poc VERDICT: PASS).
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 61019-infinite-interest-rate-bug-immunefi-folks-finance-git_exp (evm-hack-registry mirror).
- AuditVault finding: 61019-infinite-interest-rate-bug-immunefi-folks-finance-git.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "Folks Finance: Missing utilisation-ratio guard: on a fresh pool the attacker pushes totalDebt (1e18) far".
- 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.