Back to P2P Loans

An honest audit

Both FlashBank features, reviewed candidly: what they do, who you have to trust, what can go wrong, and exactly what is and isn't tested. We would rather under-claim than oversell — so this page leads with the limitations, not the badges.

No external audit. Neither contract has been reviewed by a professional auditing firm. Everything below is our own reading of our own code. The severities are our judgement, not an independent rating.

The P2P loans are now live on Ethereum and Base (mainnet, real assets), alongside a Sepolia play-money playground. They carry no external audit — only this self-review — so weigh real-money use accordingly. The Sepolia playground uses valueless test tokens (fpUSD/fpETH from the on-page faucet); never confuse the two.

Custom tokens are testnet-only for now. On mainnet the interface offers only ETH and USDC; the contract itself stays fully permissionless. The next version (FlashBankP2PLoanV2) is adversarially reviewed, unit-tested and live on the Sepolia playground (verified source) — mainnets stay on v1 until it graduates. v2 adds token sanity-checks, a graduated cooling-off fee rebate (a near-instant return costs only a 10% floor — blocking fake-token fee farming without making listing-griefing free), and pull-payout fallbacks so a blocklisted recipient can never brick the other party’s repayment or default claim. See the v2 design notes.

Open by default. Source for both contracts is verified on Etherscan and public on GitHub. Please read it, and tell us what we missed.

Flash-loan router

Custody
Non-custodial (allowance-based)
Liquidity
Stays in provider wallets
Tests
57 passing · 21 pending
Admin model
Dual-sig + single-sig emergencies
External audit
None
Upgradeable
No (immutable)

P2P term loans

Custody
Escrow between create & settle
Pricing
No oracle · time-based only
Tests
48 (v1) + 22 (v2) + live drill
Owner powers
Interface fee only (≤ 1%)
External audit
None
Network
Ethereum + Base · Sepolia demo

How to read this

StrengthBy designTrust assumptionLowMedium

Strength is something we think we got right. By design is a deliberate trade-off you should understand before using it. Trust assumption means there is a person or counterparty you are relying on. Low / Medium are issues ranked by our own estimate of impact and likelihood.

Flash-loan router

FlashBankRouter lets anyone borrow a token within a single transaction, provided they return it plus a fee before the transaction ends. Liquidity is never pooled in the contract — it stays in provider wallets and is pulled, used and returned inside one atomic call.

Custody & settlement

Providers approve the router as a spender; the router pulls only at loan time and returns funds in the same transaction. Repayment is checked by comparing balances before and after — if the borrowed amount plus fee has not come back, the whole transaction reverts. There are no price oracles and no liquidations.

Trust assumptions & findings

Strength

Non-custodial, immutable, reentrancy-guarded

Provider funds never sit in the contract. flashLoan() is nonReentrant, repayment is balance-verified, the borrower callback runs inside a try/catch, and there is no upgrade proxy — the deployed bytecode is what runs forever.

Trust assumption

A live allowance is a standing exposure

To earn fees you grant the router an ERC-20 allowance. While that allowance is live, a bug in the (immutable) router could in principle move up to the approved amount. Mitigations: the code is small and reentrancy-guarded, every loan must round-trip in one transaction, and you can pause or set your allowance to zero at any time. The provider UI now approves the exact amount for a bounded commitment (unlimited is opt-in) and has a one-click “revoke (set to 0)”.

Medium

The owner can take up to 100% of the fee

ownerFeeBps is capped at 100% of the fee (not of the loan). A misconfiguration or hostile owner could route the entire fee to the protocol, leaving providers with their principal back but no reward. Providers can pause if they dislike the split. The loan fee itself is hard-capped at 0.01%–1%.

Medium

Single-signature emergency paths exist

Most sensitive actions use a propose/execute dual-signature flow, but setTokenConfig andwithdrawOwnerProfits are callable by the owner or admin alone. A single compromised key can therefore change fees/limits/enabled-status and sweep accrued protocol fees (not provider funds).

Trust assumption

Admin rescue can move the contract's own balance

proposeRescueToken/RescueETH (dual-sig) can send any token or ETH the contract holds to any address. The router is normally near-empty, but this covers transient loan funds and accrued fees, so it is a real operator capability worth knowing about.

By design

Owner can disable a token / fee-on-transfer unsupported

Disabling a token only blocks new loans; existing commitments and balances are untouched. Rebasing and fee-on-transfer tokens are unsupported by design because settlement relies on exact balance deltas.

Low

Committed total can drift from real balances

If a provider moves funds out of their wallet, totalCommitted can overstate availability. No funds are at risk (pulls re-check the real balance at loan time); the UI reads getActualAvailableLiquidity() for an accurate figure.

Tested: the live v2.1 router has 57 passing tests covering reentrancy, failed-repayment reverts, max-borrow guards, overflow on unlimited commitments, and the dual-control flows. The 21 pending tests are a skipped suite for an experimental contract (FlashBankRevolutionary) that is not deployed — they are not a gap in the live router. We are honest that v2.1 has known centralisation trade-offs (below).

Live & verified on every chain — v3: a hardened router that caps the owner's cut at 20% of the fee, removes every single-signature path, adds a 2-day timelock on config/rescue, fixes an expired-commitment drift bug, and lets borrowers pin a maxFee on-chain. It adds 27 dedicated tests (84 passing in the suite), was integration-tested on-chain (flash loan, the maxFee pin, and reconcile), and is now deployed and verified on Ethereum, Base, Arbitrum and Sepolia. The live site now runs v3 on every chain — v2.1 held zero committed liquidity (verified on-chain), so the cutover needed no provider migration. See the improvement plan and deployment runbook. Deeper analysis lives on the security deep-dive.

P2P term loans

FlashBankP2PLoan is a neutral escrow for fixed-term, collateral-backed loans between two people. One side posts terms, the other takes them. Repay principal + a flat fee before the deadline to redeem the collateral; miss it and the lender claims it. No pools, no shared liquidity, no oracle.

Custody & settlement

The contract holds the escrowed side only between creation and settlement. Default is decided purely by the clock: after maturity + grace, an unpaid loan can be claimed. Optionally, an agreed rate(settlementValue, frozen at origination) returns any over-pledged surplus to the borrower on default — still without ever reading a price.

Trust assumptions & findings

Strength

The owner cannot touch escrowed funds

There is no rescue, no admin pull and no upgrade proxy. The owner can only set the optional interface fee (hard-capped at 1%) and where it is sent. Escrowed principal and collateral can leave only via the loan's own repay / claim / cancel paths. A conservation assert backs the disbursement maths, and it is fuzz-tested.

Trust assumption

You must vet the counterparty's tokens

Either side picks the principal and collateral tokens. A malicious offer could name a honeypot or rug token. The contract cannot know a token is “real” — always check both token addresses before you take an offer.

By design

No early liquidation — the lender carries price risk

Because nothing is priced on-chain, a lender cannot act early if collateral falls in value mid-term; they wait for the deadline. That is the deliberate cost of having no oracle. Lenders should size the fee and (optional) agreed rate accordingly.

By design

The agreed rate is a handshake, not a market price

settlementValue is whatever the two parties agree and is frozen forever. Set it high and a defaulting borrower keeps more surplus (the lender can under-recover); leave it at 0 and the lender keeps the whole pledge (the borrower can lose more than they borrowed). Both outcomes are intended and shown up front.

Strength

Offers are editable in place; the featured boost is non-refundable on cancel

You can re-price or amend an open offer's non-escrow terms with updateOffer (the agreed rate, flat fee, duration, grace and service fee) and top up placement with boostOffer — both keep your existing featured spend. Each edit bumps a version, and takeChecked pins it so a taker can't be front-run by a last-second re-price. Cancelling still refunds the escrow and listing fee but not the featured boost(an advertising spend) — which is exactly why in-place editing exists.

By design

All-or-nothing repayment; no fee-on-transfer tokens

There is no partial repayment — you redeem the whole collateral or none of it. As with the router, rebasing and fee-on-transfer tokens are rejected because terms are enforced to the exact unit.

Tested: 45 passing tests covering the full lifecycle (create/take/repay/default/cancel), the optional surplus split (including rounding in the borrower's favour), in-place offer amendments with the version-pinned take (so a re-price can't be front-run), a live re-entrancy attack via a malicious token, fee edge cases, and a conservation fuzz test. See how the mechanics work on the loans page and Lorrow compatibility.

What “tested” means here

Tests are automated checks we wrote. They catch the bugs we thought of — not the ones we didn't. They are not a guarantee of correctness, and they are not an audit. Treat a green suite as necessary, never sufficient.

Responsible disclosure

Found something we missed? Please tell us before telling the world. Open a private security advisory or an issue on GitHub. We read the code with you.