An ERC-20 with ERC-3156 flash minting and a bounded fee. A borrower can mint up to maxFlashLoan
of the token inside one transaction; after its onFlashLoan callback runs, the minted amount is burned
and a bounded fee is pulled to a treasury — all atomically. Net total supply is unchanged by any flash
loan. MIT.
A pool-based flash loan lends out existing liquidity, so its ceiling is the pool size. A flash
mint creates the liquidity on demand and destroys it in the same tx — so the ceiling is
type(uint256).max − totalSupply, and there is no pool to drain. Useful for closing an arbitrage or
refinancing a position without fronting capital.
flashLoan(receiver, token, amount, data)(ERC-3156): mintsamounttoreceiver, callsreceiver.onFlashLoan(...), then requiresreceiverto have approved this contract foramount + feeand burnsamount+ transfersfeeto the treasury.receivermust return the ERC-3156 magic value.flashFee(token, amount) = amount * flashFeeBps / 1e4, withflashFeeBpshard-capped at 10%.- The fee is paid from the borrower's real balance (the minted amount is burned), so a profitable flash mint must actually earn at least the fee.
- Owner can
mintcirculating supply,setFlashFeeBps(≤ cap), andsetTreasury(non-zero). No admin path to holder balances.
- Supply conservation —
totalSupplyalways equals the ghost sum of ownermints, across any sequence of flash loans (any size, any fee, including nested/re-entrant loans). Flash loans mint-then- burn net-zero; fees only move existing tokens. 12,800 calls, 0 reverts. Mutation-checked (zeroing the fee fails the fee tests).
- Nested/re-entrant flash loans are allowed by design (each is self-balancing); supply stays conserved — tested.
- The token is a plain ERC-20 otherwise (no rebasing/hooks). Unaudited reference implementation.
forge test # 15 tests: happy path, fee, maxFlashLoan, nested loans, revert paths, admin, supply invariant