Skip to content

Flash Loans

Mihai edited this page Sep 6, 2026 · 2 revisions

Flash Loans

A cash flash loan temporarily lends pool tokens to a receiver contract. The receiver must make principal plus the market fee available for repayment within the same transaction. Failure at any step rolls back the whole transaction.

A cash flash loan creates no lending account or persistent debt. For a callback that leaves an open collateralized borrowing position, see flash positions in Strategies.

Requirements

The initiator authorizes the controller call and identifies the hub market, amount, receiver, and opaque callback data. The receiver must be a deployed Wasm contract.

The controller must be unpaused, the hub active, and the selected pool market configured to allow flash loans. The requested amount must be positive and fit that market's booked cash. The call runs inside the controller's flash guard, which rejects protected monetary reentry.

Cash flash loans do not value an account or fetch an oracle price. Their repayment proof is the pool's observed balance in the loaned token.

Principal and fee

The pool calculates the fee from its current market settings. The initiator does not supply a fee that the pool trusts.

let fee = half_up(principal * fee_bps / BPS);
let fee = if fee_bps > 0 { max(fee, 1) } else { 0 };
let repayment = principal + fee;

Principal, fee, and repayment use the token's native base units. The configured fee is limited to 500 BPS, or 5%. A positive fee rate therefore still charges one base unit when the proportional fee rounds to zero.

Settlement

The pool checks exact balances throughout the call:

  1. Accrue the market, check flash-loan eligibility and cash, and snapshot the pool's token balance.
  2. Transfer principal to the receiver. The pool balance must equal the snapshot minus principal.
  3. Invoke the receiver callback. When it returns, the pool balance must still equal the snapshot minus principal.
  4. Check that the receiver's allowance to the pool covers principal plus fee.
  5. Pull exactly principal plus fee from the receiver using the token's transfer_from.
  6. Require the final pool balance to equal the initial snapshot plus fee, then book the fee as cash and protocol revenue.
let balance_after_payout = balance_before - principal;
let balance_after_callback = balance_before - principal;
let balance_after_repayment = balance_before + fee;

These are equality checks. Sending repayment directly to the pool during the callback fails the intermediate check; repayment is collected by the pool's pull. An unrelated donation during the callback also fails that check. A callback return value cannot substitute for token repayment.

sequenceDiagram
    actor Initiator
    participant Controller
    participant Pool
    participant Receiver
    Initiator->>Controller: Authorize cash flash loan
    Controller->>Pool: Enter guarded loan call
    Pool->>Pool: Check cash and snapshot token balance
    Pool->>Receiver: Send principal
    Pool->>Pool: Require exact post-payout balance
    Pool->>Receiver: Invoke callback
    Receiver->>Receiver: Execute logic and approve repayment
    Pool->>Pool: Require unchanged post-payout balance
    Pool->>Receiver: Pull principal plus fee
    Pool->>Pool: Require exact final balance and book fee
    Pool-->>Controller: Return charged fee
Loading

Receiver integration

Implement this callback:

execute_flash_loan(
    initiator: Address,
    asset: Address,
    amount: i128,
    fee: i128,
    pool: Address,
    data: Bytes,
)

The callback's asset is the token address; the controller entry point selects the market with a hub ID and token address. The data bytes pass through unchanged.

The receiver obtains enough of the loaned token to cover the principal and fee, then approves the pool as spender for repayment with a valid allowance expiration. This is a token allowance used by the pool's subsequent pull. It is different from the exact transfer authorization used by the strategy router.

A receiver should validate the expected lending contract and callback terms before using its own funds or permissions. The protocol's repayment checks protect the pool; they do not establish that every receiver's application logic is safe.

Exact public signatures are in the endpoint reference.

Failure and trust boundaries

Insufficient cash, disabled flash loans, an invalid receiver, insufficient allowance, a callback failure, or any balance mismatch aborts the transaction. Protected controller monetary entry points reject reentry during the callback window.

The checks depend on the loaned token reporting honest balances and enforcing transfers and allowances correctly. They do not support arbitrary fee-on-transfer or rebasing behavior merely because a balance is measured.

See Central Pool for the distinction between booked cash and physical token balances, and Security for external-contract assumptions.

Clone this wiki locally