{"id":"ERC-3156","name":"Flash Loans","status":"Final","chain":"both","category":{"id":"defi","name":"DeFi Patterns","description":"Vaults, bonds, and financial primitives"},"journeyStages":[{"id":"executing","name":"Executing Transactions","description":"Performing on-chain actions"}],"uxImpact":"ERC-3156 standardizes flash loans: a receiver borrows without upfront collateral, uses the funds, and repays principal plus fee in one transaction. If repayment or the callback fails, the loan state reverts, while gas is still spent and unsafe approvals or untrusted lenders remain risks.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-3156","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-3156","specConstraints":[{"id":"erc-3156-lender-interface","constraint":"A compatible flash lender implements the IERC3156FlashLender interface.","appliesTo":"infrastructure","normativity":"normative","specQuote":"A `lender` MUST implement the IERC3156FlashLender interface.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Feature-detect the lender interface before offering a flash-loan flow, and label the selected lender rather than implying that every liquidity source supports the same callback behavior."},{"id":"erc-3156-max-loan-capability","constraint":"maxFlashLoan reports the maximum supported amount and returns zero for an unsupported token.","appliesTo":"application","normativity":"normative","specQuote":"The `maxFlashLoan` function MUST return the maximum loan possible for `token`. If a `token` is not currently supported `maxFlashLoan` MUST return 0, instead of reverting.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Show the lender's current available ceiling and treat zero as unsupported rather than as a failed balance lookup."},{"id":"erc-3156-fee-quote","constraint":"flashFee reports the fee for the selected token and amount and reverts for an unsupported token.","appliesTo":"application","normativity":"normative","specQuote":"The `flashFee` function MUST return the fee charged for a loan of `amount` `token`. If the token is not supported `flashFee` MUST revert.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Calculate and show the lender fee for the chosen asset and amount before the user approves the transaction, with unsupported-token recovery distinct from a generic quote failure."},{"id":"erc-3156-callback-context","constraint":"The lender passes the initiating caller as initiator to the receiver callback.","appliesTo":"account-implementation","normativity":"normative","specQuote":"The `flashLoan` function MUST include `msg.sender` as the `initiator` to `onFlashLoan`.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Keep the initiator visible in receiver validation and do not treat callback data alone as proof of who started the loan."},{"id":"erc-3156-fee-consistency","constraint":"The callback fee must equal flashFee(token, amount).","appliesTo":"account-implementation","normativity":"normative","specQuote":"The `flashLoan` function MUST include a `fee` argument to `onFlashLoan` with the fee to pay for the loan on top of the principal, ensuring that `fee == flashFee(token, amount)`.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Show principal and fee as separate values and make the receiver's repayment review use the same quote that the lender passes to the callback."},{"id":"erc-3156-repayment-amount","constraint":"After the callback, the lender takes principal plus fee from the receiver or reverts.","appliesTo":"application","normativity":"normative","specQuote":"After the callback, the `flashLoan` function MUST take the `amount + fee` `token` from the `receiver`, or revert if this is not successful.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Set expectations that a flash-loan action is atomic: failed repayment reverts the transaction, while gas and any external side effects still need to be explained by the surrounding product."},{"id":"erc-3156-repayment-approval","constraint":"The receiver must approve principal plus fee before onFlashLoan ends for the transaction not to revert.","appliesTo":"account-implementation","normativity":"normative","specQuote":"For the transaction to not revert, `receiver` MUST approve `amount + fee` of `token` to be taken by `msg.sender` before the end of `onFlashLoan`.","specSection":"Specification — Receiver Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#receiver-specification","designImplication":"Make the approval and repayment allowance explicit in the receiver implementation and review the lender address before granting it."},{"id":"erc-3156-callback-trust","constraint":"Callback arguments cannot be trusted without verification; lender and initiator trust are required before treating token, amount, fee, or data as genuine.","appliesTo":"account-implementation","normativity":"security-considerations","specQuote":"The arguments of `onFlashLoan` are expected to reflect the conditions of the flash loan, but cannot be trusted unconditionally. They can be divided in two groups, that require different checks before they can be trusted to be genuine.\n\n0. No arguments can be assumed to be genuine without some kind of verification. `initiator`, `token` and `amount` refer to a past transaction that might not have happened if the caller of `onFlashLoan` decides to lie. `fee` might be false or calculated incorrectly. `data` might have been manipulated by the caller.\n1. To trust that the value of `initiator`, `token`, `amount` and `fee` are genuine a reasonable pattern is to verify that the `onFlashLoan` caller is in a whitelist of verified flash lenders. Since often the caller of `flashLoan` will also be receiving the `onFlashLoan` callback this will be trivial. In all other cases flash lenders will need to be approved if the arguments in `onFlashLoan` are to be trusted.\n2. To trust that the value of `data` is genuine, in addition to the check in point 1, it is recommended to verify that the `initiator` belongs to a group of trusted addresses. Trusting the `lender` and the `initiator` is enough to trust that the contents of `data` are genuine.","specSection":"Security Considerations — Verification of callback arguments","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#verification-of-callback-arguments","designImplication":"Whitelist or otherwise authenticate the lender and initiator before acting on callback values. Do not let arbitrary callback data determine a high-value swap, repayment, or approval."},{"id":"erc-3156-automatic-approval-risk","constraint":"Standing or automatic approvals can let an attacker drain a receiver up to its allowance or balance if lender and callback validation are missing.","appliesTo":"account-implementation","normativity":"security-considerations","specQuote":"If an unsuspecting contract with a non-reverting fallback function, or an EOA, would approve a `lender` implementing ERC3156, and not immediately use the approval, and if the `lender` would not verify the return value of `onFlashLoan`, then the unsuspecting contract or EOA could be drained of funds up to their allowance or balance limit.","specSection":"Security Considerations — Flash lending security considerations — Automatic approvals","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#automatic-approvals","designImplication":"Prefer scoped or just-in-time approvals and make the spender, amount, and callback validation visible. Never present a persistent flash-lender allowance as harmless convenience."},{"id":"erc-3156-flash-mint-amount-risk","constraint":"Flash mint integrations need explicit limits or overflow-safe handling because an unconstrained provider can mint up to 2^256-1 tokens in one transaction.","appliesTo":"account-implementation","normativity":"security-considerations","specQuote":"If the flash mint provider does not place any limits on the amount of flash mintable tokens in a transaction, then anyone can flash mint 2^256-1 amount of tokens.\n\nThe protocols on the receiving end of the flash mints will need to ensure their contracts can handle this, either by using a compiler that embeds overflow protection in the smart contract bytecode, or by setting explicit checks.","specSection":"Security Considerations — Flash minting external security considerations — Example 2 - arithmetic overflow and underflow","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#example-2---arithmetic-overflow-and-underflow","designImplication":"Show provider limits and require receiving protocols to use checked arithmetic or explicit bounds. Do not treat a successful flash-mint quote as economically bounded by ordinary balances."},{"id":"erc-3156-composed-feature-risk","constraint":"Combining flash minting with business-specific features in one platform can create unintended consequences.","appliesTo":"application","normativity":"security-considerations","specQuote":"The coupling of flash minting with business specific features in the same platform can easily lead to unintended consequences.","specSection":"Security Considerations — Flash minting internal security considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#flash-minting-internal-security-considerations","designImplication":"Review flash-mint composition with lending, redemption, and treasury limits together. Avoid a one-click flow that hides how temporary liquidity changes downstream accounting."},{"id":"erc-3156-callback-required","constraint":"flashLoan must invoke the receiver's onFlashLoan callback.","appliesTo":"account-implementation","normativity":"normative","specQuote":"The `flashLoan` function MUST include a callback to the `onFlashLoan` function in a `IERC3156FlashBorrower` contract.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Show the receiver callback as part of the atomic transaction plan; do not represent the loan as a passive balance transfer."},{"id":"erc-3156-funds-before-callback","constraint":"The lender transfers the requested token amount to the receiver before invoking the callback.","appliesTo":"account-implementation","normativity":"normative","specQuote":"The `flashLoan` function MUST transfer `amount` of `token` to `receiver` before the callback to the receiver.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Keep the temporary balance and callback step distinct in simulations and transaction previews."},{"id":"erc-3156-callback-arguments","constraint":"The lender passes the original token, amount, and data values unchanged to onFlashLoan.","appliesTo":"account-implementation","normativity":"normative","specQuote":"The `flashLoan` function MUST NOT modify the `token`, `amount` and `data` parameter received, and MUST pass them on to `onFlashLoan`.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Display the exact asset, amount, and strategy data that the receiver will validate, rather than showing a transformed callback payload."},{"id":"erc-3156-callback-sentinel","constraint":"The lender and receiver validate the onFlashLoan callback using the ERC3156FlashBorrower.onFlashLoan hash.","appliesTo":"account-implementation","normativity":"normative","specQuote":"The `lender` MUST verify that the `onFlashLoan` callback returns the keccak256 hash of \"ERC3156FlashBorrower.onFlashLoan\".","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Keep an invalid callback return distinct from insufficient repayment and expose it as a protocol validation failure."},{"id":"erc-3156-success-result","constraint":"A successful flashLoan returns true.","appliesTo":"application","normativity":"normative","specQuote":"If successful, `flashLoan` MUST return `true`.","specSection":"Specification — Lender Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#lender-specification","designImplication":"Use both the transaction receipt and returned success semantics when presenting completion; do not treat an attempted callback as success."},{"id":"erc-3156-receiver-interface","constraint":"A flash-loan receiver implements IERC3156FlashBorrower.","appliesTo":"account-implementation","normativity":"normative","specQuote":"A `receiver` of flash loans MUST implement the IERC3156FlashBorrower interface:","specSection":"Specification — Receiver Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#receiver-specification","designImplication":"Feature-detect the receiver callback before offering a strategy and identify which contract receives temporary funds."},{"id":"erc-3156-interest-rate-guard","constraint":"Receiving lending protocols should use flat interest-rate floors and ceilings and rebalance rates for flash-induced liquidity changes.","appliesTo":"account-implementation","normativity":"security-considerations","specQuote":"If there exists a lending protocol that offers stable interests rates, but it does not have floor/ceiling rate limits and it does not rebalance the fixed rate based on flash-induced liquidity changes, then it could be susceptible to the following scenario:\n\nFreeLoanAttack.sol\n1. Flash mint 1 quintillion STAB\n2. Deposit the 1 quintillion STAB + $1.5 million worth of ETH collateral\n3. The quantum of your total deposit now pushes the stable interest rate down to 0.00001% stable interest rate\n4. Borrow 1 million STAB on 0.00001% stable interest rate based on the 1.5M ETH collateral\n5. Withdraw and burn the 1 quint STAB to close the original flash mint\n6. You now have a 1 million STAB loan that is practically interest free for perpetuity ($0.10 / year in interest)\n\nThe key takeaway being the obvious need to implement a flat floor/ceiling rate limit and to rebalance the rate based on short term liquidity changes.","specSection":"Security Considerations — Flash minting external security considerations — Example 1 - interest rate attack","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#example-1---interest-rate-attack","designImplication":"Show flash-mint liquidity assumptions in lending previews and preserve rate guardrails when temporary supply can affect pricing or borrowing power."},{"id":"erc-3156-treasury-drain-risk","constraint":"Composed flash-mint and treasury borrowing flows can push an underlying lender to its limit and enable liquidation of the flash lender.","appliesTo":"account-implementation","normativity":"security-considerations","specQuote":"Assume a smart contract that flash lends its native token. The same smart contract borrows from a third party when users burn the native token. This pattern would be used to aggregate in the smart contract the collateralized debt of several users into a single account in the third party. The flash mint could be used to cause the lender to borrow to its limit, and then pushing interest rates in the underlying lender, liquidate the flash lender:\n1. Flash mint from `lender` a very large amount of FOO.\n2. Redeem FOO for BAR, causing `lender` to borrow from `underwriter` all the way to its borrowing limit.\n3. Trigger a debt rate increase in `underwriter`, making `lender` undercollateralized.\n4. Liquidate the `lender` for profit.","specSection":"Security Considerations — Flash minting internal security considerations — Example - Treasury draining","specUrl":"https://ercs.ethereum.org/ERCS/erc-3156#example---treasury-draining","designImplication":"Keep flash liquidity, treasury debt, collateral, and liquidation limits visible as one composed risk model rather than isolating the flash-loan step in a simplified confirmation."}],"summary":"ERC-3156 standardizes flash loans: a receiver borrows without upfront collateral, uses the funds, and repays principal plus fee in one transaction. If repayment or the callback fails, the loan state reverts, while gas is still spent and unsafe approvals or untrusted lenders remain risks.","applicability":{"whenToUse":["Your product addresses: arbitrage requires upfront capital.","Your product addresses: each protocol has different flash loan interfaces.","The flow should show borrow amount, lender fee, gas cost, repayment, and simulated net result before execution.","You are designing a one-click collateral swap experience with visible states and recovery paths."],"whenToAvoid":["The product never invokes a flash lender or receiver callback.","The flow has no atomic borrow-and-repay transaction to explain.","No lender, receiver, or approval trust boundary is available to verify.","No token balances, swaps, lending, or yield flows appear in the product."]},"designerTakeaways":["You can design UI that shows a lender-supported borrow amount, fee, gas cost, and repayment.","You can use the standard interface across lenders that implement ERC-3156.","Design the flow to support flash loan to swap collateral atomically in one transaction."],"problemsSolved":[{"problem":"Arbitrage requires upfront capital","oldWay":"Need $100K to capture $100K arbitrage opportunity","newWay":"Borrow a lender-supported amount, execute the strategy, repay principal plus fee, and keep any simulated surplus after gas.","impact":"critical"},{"problem":"Each protocol has different flash loan interfaces","oldWay":"Lender-specific flash-loan interfaces require separate integrations","newWay":"Standard interface works across all ERC-3156 lenders","impact":"high"},{"problem":"Swapping collateral requires complex multi-step process","oldWay":"Withdraw collateral → sell → buy new → redeposit (risky)","newWay":"Flash loan to swap collateral atomically in one transaction","impact":"high"},{"problem":"Self-liquidation is expensive and slow","oldWay":"Find capital to repay debt before liquidation hits","newWay":"Flash loan to repay, withdraw collateral, sell enough, repay flash loan","impact":"high"},{"problem":"Building flash loan integrations is complex","oldWay":"Custom code for each lending protocol","newWay":"Standard receiver callback simplifies integration","impact":"medium"}],"uxPatterns":[{"name":"One-Click Collateral Swap","description":"Change your collateral type without closing position","userFlow":["User views current position","Selects new collateral type","Clicks \"Swap Collateral\"","Behind scenes: flash loan repays debt, withdraw ETH, swap to wstETH, redeposit, reborrow, repay flash loan","All happens in one transaction","User sees new collateral, same debt"]},{"name":"Self-Liquidation Protection","description":"Close position before liquidators take penalty","userFlow":["User alerted to low health factor","Sees comparison: external liquidation vs self-liquidation","Clicks \"Self-Liquidate\"","Flash loan: borrow USDC → repay debt → withdraw collateral → sell enough for flash loan + fee → repay flash loan","User sees any remaining collateral after debt, fees, and gas","Shows whether the simulated path may avoid a liquidation penalty"]},{"name":"Leverage Adjustment","description":"Increase or decrease leverage in one click","userFlow":["User views current leverage","Adjusts slider to desired leverage","UI shows position change preview","User confirms","Flash loan executes complex rebalance","Position updated in one transaction"]},{"name":"Arbitrage Opportunity","description":"Capture price differences across DEXs","userFlow":["System detects price difference","Shows opportunity to user","User reviews profit/fee breakdown","Clicks Execute","Flash loan: borrow → buy low → sell high → repay + keep profit","Profit deposited to user wallet"]}],"uiComponents":[{"name":"FlashLoanIndicator","description":"Shows operation uses flash loan","states":["using-flash-loan","direct-capital","hybrid"],"props":["lender","amount","fee","tooltip"]},{"name":"AtomicOperationPreview","description":"Shows all steps that happen in one transaction","states":["loading","ready","executing","complete"],"props":["steps[]","netResult","gasEstimate"]},{"name":"CollateralSwapForm","description":"Interface for collateral type changes","states":["editing","simulating","executing","success"],"props":["fromAsset","toAsset","position","onSwap"]},{"name":"LeverageAdjuster","description":"Slider for leverage changes","states":["idle","adjusting","confirming","applied"],"props":["currentLeverage","maxLeverage","onChange","healthFactor"]},{"name":"ProfitBreakdown","description":"Shows gross profit, fees, net result","states":["profitable","break-even","unprofitable"],"props":["grossProfit","flashLoanFee","gasCost","netProfit"]}],"antiPatterns":[{"pattern":"Not explaining what a flash loan is","why":"Users scared of \"borrowing millions\" language","instead":"Explain: \"Borrow → use → repay in one transaction; a failed callback rolls back loan state, but gas is still spent.\"","severity":"high"},{"pattern":"Hiding the flash loan fee","why":"Users surprised by unexpected cost","instead":"Query flashFee for the selected lender, token, and amount, then show the returned fee prominently","severity":"high"},{"pattern":"Not showing all-or-nothing guarantee","why":"Users fear losing funds if something fails","instead":"Explain the atomic state rollback, show gas and approval risks, and verify the lender and initiator.","severity":"critical"},{"pattern":"Complex multi-step explanations","why":"Users don't need to understand 7-step atomic operation","instead":"Show outcome: \"Swap collateral from ETH to wstETH\"","severity":"medium"},{"pattern":"Letting users execute unprofitable arbitrage","why":"Gas + fee exceeds profit = user loses money","instead":"Disable execute button if net profit is negative","severity":"critical"},{"pattern":"Not simulating the transaction first","why":"Flash loan txs are complex, may fail unexpectedly","instead":"Always simulate and show expected outcome before execution","severity":"high"}],"keyTakeaways":["Flash loans = borrow → use → repay in one transaction","No upfront collateral, with atomic loan-state rollback but gas and approval risks","Always show the fee and net profit clearly","Simulate before executing to catch failures","Abstract complexity: show outcome, not the 7 steps"],"technicalNotes":"ERC-3156 defines flashLoan(receiver, token, amount, data) on lenders and onFlashLoan(initiator, token, amount, fee, data) callbacks on receivers. The receiver must repay amount plus the lender's flashFee(token, amount); if repayment or the callback fails, the transaction reverts. Verify the lender and initiator before trusting callback arguments, use bounded approvals, and remember that reverted execution still consumes gas. The standard does not prescribe a percentage fee.","lastUpdated":"2026-09-18","sources":[{"label":"ERC-3156 official specification","url":"https://ercs.ethereum.org/ERCS/erc-3156","type":"official-spec"}],"lastReviewed":"2026-09-18"},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-3156","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-3156","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-3156","markdown":"https://www.eipsfordesigners.com/standards/ERC-3156/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-3156/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-3156","official":"https://ercs.ethereum.org/ERCS/erc-3156","discussion":"https://ethereum-magicians.org/search?q=ERC-3156"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}