# Scallop Flash Loan

> Execute Scallop flash loans. Use when user says "flash loan", "flashloan", "uncollateralized borrow", "arbitrage", "same-transaction loan", or asks about flash loan strategies on Scallop.

- Skill: `scallop-io/scallop-flash-loan` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add scallop-io/scallop-flash-loan`
- Raw SKILL.md: https://api.skillmd.com/api/skills/scallop-io/scallop-flash-loan/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: scallop-io (https://skillmd.com/u/scallop-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/scallop-io/scallop-flash-loan

---


# Flash Loans

Execute uncollateralized flash loans on Scallop for arbitrage, liquidations, and collateral swaps.

## Overview

Flash loans allow borrowing without collateral, as long as the loan is repaid within the same transaction. If not repaid, the entire transaction reverts.

## Key Properties

- **No Collateral Required**: Borrow any available amount
- **Same-Transaction Repay**: Must repay before transaction ends
- **Fee**: Small fee added to repay amount
- **Atomic**: All-or-nothing execution

## Return Type

`borrow_flash_loan()` returns `tuple[TxResult, TxResult]` — nested PTB result handles for the borrowed coin and flash loan receipt:

```python
coin_result, receipt_result = tx.borrow_flash_loan(amount, coin_name)
# coin_result: TxResult handle for the borrowed coin
# receipt_result: TxResult handle for the flash loan receipt
```

These `TxResult` handles can be passed directly to subsequent calls like `repay_flash_loan()`, `supply()`, and `liquidate()`.

## Basic Flash Loan

### Python

```python
tx = builder.create_tx_block()

# Borrow 1000 USDC via flash loan
# Returns tuple[TxResult, TxResult]: (coin, receipt)
usdc_coin, flash_receipt = tx.borrow_flash_loan(
    amount=1_000_000_000,  # 1000 USDC (6 decimals)
    coin_name="usdc"
)

# === Use the borrowed funds here ===
# Example: swap, liquidate, arbitrage, etc.

# Repay flash loan (amount + fee)
tx.repay_flash_loan(usdc_coin, flash_receipt, "usdc")

result = builder.sign_and_send_tx_block(tx)
print(f"Flash loan TX: {result.digest}")
```

### TypeScript

```typescript
const tx = builder.createTxBlock();

// Borrow
const [usdcCoin, flashReceipt] = await tx.borrowFlashLoan(1_000_000_000, 'usdc');

// ... use funds ...

// Repay
await tx.repayFlashLoan(usdcCoin, flashReceipt, 'usdc');

const result = await builder.signAndSendTxBlock(tx);
```

## Flash Loan Fee

Flash loans have a small per-asset fee:

```
repay_amount = borrowed_amount + (borrowed_amount * fee_rate)
fee_rate     = fee_numerator / fee_denominator   # stored on-chain per asset;
                                                 # both SDKs return the ratio pre-computed
```

Indicative rates (USDC, SUI and most assets sit at 0.05%, with some at 0.05%–0.1%) — **do not hard-code these in profitability math**. Fees can be changed by governance; query them live before each run.

### Query Live Fee Rates (TypeScript)

```typescript
const scallopSDK = new Scallop({ networkType: 'mainnet' });
await scallopSDK.init();
const query = scallopSDK.client.query;

// Returns Record<coinName, number> — the fee RATIO is already computed
// (fee numerator divided by the on-chain denominator). There is no
// { fee, feeScale } object shape.
const fees = await query.getFlashLoanFees(['usdc', 'sui']);
const usdcRate = fees.usdc; // e.g. 0.0005 for 0.05%
console.log(`Live USDC flash-loan fee: ${(usdcRate * 100).toFixed(4)}%`);

// Use the live rate in profitability checks
const feeAmount  = borrowAmount * usdcRate;
const repayTotal = borrowAmount + feeAmount;
```

> Always call `getFlashLoanFees` through the `ScallopQuery` instance — the underlying repository helper is internal and not re-exported from the package root.

The Python SDK (`sui-scallop-sdk` >= 0.3.0a1) wraps the same query: `query.get_flash_loan_fees(coin_names)` returns `dict[str, Decimal]` (fee ratios), and `query.get_flash_loan_fee(coin_name)` returns a single `Decimal`.

## Use Case 1: Arbitrage

Profit from price differences across DEXes:

```python
tx = builder.create_tx_block()

# 1. Flash borrow 10,000 USDC
usdc_coin, receipt = tx.borrow_flash_loan(10_000_000_000, "usdc")

# 2. Buy SUI on DEX A (lower price)
sui_coin = dex_a.swap(usdc_coin, "usdc", "sui")

# 3. Sell SUI on DEX B (higher price)
usdc_profit = dex_b.swap(sui_coin, "sui", "usdc")

# 4. Repay flash loan (keep profit)
tx.repay_flash_loan(usdc_profit, receipt, "usdc")

# 5. Transfer remaining profit
tx.transfer_objects([remaining_usdc], wallet_address)

result = builder.sign_and_send_tx_block(tx)
```

> A visible price gap is not profit — slippage, the loan fee, competition and two-sided depth all
> come out of it first. Sizing and pre-submit checks:
> [arbitrage-examples.md](references/arbitrage-examples.md).

## Use Case 2: Liquidation

Liquidate without capital:

```python
tx = builder.create_tx_block()

# 1. Flash borrow to repay target's debt
usdc_coin, receipt = tx.borrow_flash_loan(repay_amount, "usdc")

# 2. Liquidate underwater position
# Returns tuple[TxResult, TxResult]: (remaining_debt, collateral)
remaining_debt, collateral = tx.liquidate(
    obligation_id=target_obligation_id,
    repay_coin_idx=usdc_coin,
    debt_coin_name="usdc",
    collateral_coin_name="sui",
)

# 3. Swap some collateral to USDC for repayment
usdc_for_repay = dex.swap(collateral_portion, "sui", "usdc")

# 4. Repay flash loan
tx.repay_flash_loan(usdc_for_repay, receipt, "usdc")

# 5. Keep remaining collateral as profit
tx.transfer_objects([remaining_collateral], wallet_address)

result = builder.sign_and_send_tx_block(tx)
```

## Advanced Patterns

Three further compositions are covered in
[flash-loan-patterns.md](references/flash-loan-patterns.md):

- **Collateral swap** — change collateral type without closing the position, using the borrowed
  asset as temporary scaffolding.
- **Leverage loop** — assemble a leveraged position atomically instead of looping deposit-and-borrow.
- **Multi-asset flash loan** — borrow several assets at once; each receipt must be repaid with its
  matching asset.

## Error Handling

### Transaction Will Fail If:

1. **Not Repaid**: Flash loan not repaid before tx ends
2. **Wrong Receipt**: Using wrong receipt for repay
3. **Insufficient Repay**: Repay amount less than required
4. **Liquidity**: Market doesn't have enough to lend

### Error Codes

| Code | Error | Cause |
|------|-------|-------|
| 701 | `FlashLoanNotRepaid` | Loan not repaid in same tx |
| 702 | `FlashLoanAmountTooHigh` | Exceeds available liquidity |
| 703 | `InvalidFlashLoanReceipt` | Wrong receipt used |

### Safe Pattern

```python
def safe_flash_loan(builder, operations_fn, amount, coin_name, wallet):
    tx = builder.create_tx_block()

    try:
        # Borrow
        coin, receipt = tx.borrow_flash_loan(amount, coin_name)

        # Execute custom operations
        result_coin = operations_fn(tx, coin)

        # Repay
        tx.repay_flash_loan(result_coin, receipt, coin_name)

        return builder.sign_and_send_tx_block(tx)

    except Exception as e:
        # Transaction automatically reverts
        raise Exception(f"Flash loan failed: {e}")
```

## Profitability Check

Before executing, verify profitability:

```python
def is_profitable(borrow_amount, expected_return, fee_rate, gas_cost=0.01):
    """Check if flash loan operation is profitable.

    fee_rate MUST be pulled live (via queryFlashLoanFees in the TS SDK,
    or a raw RPC read of the FlashLoanFee object). Do not pass a hard-coded value.
    """
    fee = borrow_amount * fee_rate
    total_cost = borrow_amount + fee + gas_cost

    profit = expected_return - total_cost

    return profit > 0, profit
```

## Available Liquidity

Check available flash loan amount:

```python
query = client.create_query()

# get_market_data() returns dict[str, MarketPool]
market = query.get_market_data()

for coin_name, pool in market.items():
    print(f"{coin_name}: pool data available for flash loan check")
```

> **Note**: The Python SDK's `get_market_data()` implementation is still maturing. For detailed liquidity data, use the TypeScript SDK or Scallop app.

## References

- [Flash Loan Patterns](references/flash-loan-patterns.md) - Advanced patterns
- [Arbitrage Examples](references/arbitrage-examples.md) - Arbitrage strategies
- [Error Codes](../../references/error-codes.md) - Error reference

