LP-3027
ImplementedLRC-20 FlashMint Extension
Flash minting extension for LRC-20 tokens enabling uncollateralized borrowing within a single transaction
LP-3027: LRC-20 FlashMint Extension
Abstract
This LP defines the FlashMint extension for LRC-20 tokens, enabling tokens to be minted, used, and burned within a single transaction without collateral.
Motivation
Flash minting provides:
- Uncollateralized borrowing for arbitrage
- Capital-efficient DeFi operations
- No pre-existing liquidity requirements
- Lower barriers for market makers
Unlike flash loans (LP-3156) which lend from a pool, flash minting creates new tokens temporarily.
Specification
Interface
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.31;
import "./ILRC20.sol";
import "../interfaces/ILRC3156FlashLender.sol";
/**
* @title ILRC20FlashMint
* @notice LRC-20 extension for flash minting
*/
interface ILRC20FlashMint is ILRC20, ILRC3156FlashLender {
/**
* @notice Returns maximum flash mint amount
* @param token Token address (must be this contract)
* @return Maximum flash mintable amount
*/
function maxFlashLoan(address token) external view returns (uint256);
/**
* @notice Returns flash mint fee
* @param token Token address
* @param amount Flash mint amount
* @return Fee amount
*/
function flashFee(address token, uint256 amount) external view returns (uint256);
/**
* @notice Execute flash mint
* @param receiver Callback receiver
* @param token Token to flash mint
* @param amount Amount to mint
* @param data Callback data
* @return Success boolean
*/
function flashLoan(
ILRC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}
Implementation
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.31;
import "./LRC20.sol";
import "../interfaces/ILRC3156FlashBorrower.sol";
/**
* @title LRC20FlashMint
* @notice LRC-20 with flash minting capability
*/
abstract contract LRC20FlashMint is LRC20 {
bytes32 private constant CALLBACK_SUCCESS = keccak256("LRC3156FlashBorrower.onFlashLoan");
error LRC20FlashMintUnsupportedToken(address token);
error LRC20FlashMintExceededMaxLoan(uint256 maxLoan);
error LRC20FlashMintCallbackFailed();
error LRC20FlashMintRepayFailed();
/**
* @notice Returns maximum flash mintable amount
* @dev Can be overridden to set custom limits
*/
function maxFlashLoan(address token) public view virtual returns (uint256) {
return token == address(this) ? type(uint256).max - totalSupply() : 0;
}
/**
* @notice Returns flash mint fee (default: 0)
* @dev Can be overridden to charge fees
*/
function flashFee(address token, uint256 amount) public view virtual returns (uint256) {
if (token != address(this)) {
revert LRC20FlashMintUnsupportedToken(token);
}
return _flashFee(amount);
}
/**
* @dev Internal fee calculation (default: 0)
*/
function _flashFee(uint256 amount) internal view virtual returns (uint256) {
return 0;
}
/**
* @dev Internal fee receiver (default: address(0) = burn)
*/
function _flashFeeReceiver() internal view virtual returns (address) {
return address(0);
}
/**
* @notice Execute flash mint
*/
function flashLoan(
ILRC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) public virtual returns (bool) {
uint256 maxLoan = maxFlashLoan(token);
if (amount > maxLoan) {
revert LRC20FlashMintExceededMaxLoan(maxLoan);
}
uint256 fee = flashFee(token, amount);
// Mint tokens to receiver
_mint(address(receiver), amount);
// Execute callback
if (receiver.onFlashLoan(msg.sender, token, amount, fee, data) != CALLBACK_SUCCESS) {
revert LRC20FlashMintCallbackFailed();
}
// Collect repayment + fee
address feeReceiver = _flashFeeReceiver();
_burn(address(receiver), amount);
if (fee > 0 && feeReceiver != address(0)) {
_transfer(address(receiver), feeReceiver, fee);
} else if (fee > 0) {
_burn(address(receiver), fee);
}
return true;
}
}
Rationale
LRC-3156 Compatibility
Implements the standard flash loan interface (LP-3156) for:
- Interoperability with existing flash loan tooling
- Consistent borrower callback pattern
- Familiar developer experience
Zero Default Fee
Default fee of 0 because:
- Minting has no opportunity cost
- Encourages protocol adoption
- Fee can be overridden by implementations
Supply Cap Protection
maxFlashLoan prevents supply overflow by limiting flash mint to type(uint256).max - totalSupply().
Backwards Compatibility
This extension is fully backwards compatible with LRC-20:
- Interface: Extends
ILRC20without modifying core functions - Storage: Uses separate storage slots for flash mint parameters
- Events: Inherits LRC-20 events; no new events required
- EIP-3156: Compatible with EIP-3156 flash loan standard
Existing LRC-20 implementations can be upgraded by:
- Inheriting
LRC20FlashMintinstead ofLRC20 - Overriding
_flashFee()and_flashFeeReceiver()if custom fees desired - Adding reentrancy protection in callback receivers
Use Cases
- Arbitrage: Flash mint stablecoins for cross-DEX arbitrage
- Liquidations: Flash mint to liquidate undercollateralized positions
- Collateral Swaps: Flash mint to swap collateral without unwinding positions
- Self-Liquidation: Flash mint to repay and withdraw in one transaction
Security Considerations
- Reentrancy: Flash mints execute untrusted callbacks; use reentrancy guards
- Callback Validation: Verify
onFlashLoanreturns correct magic value - Supply Overflow: Validate max flash loan doesn't exceed uint256 max
- Fee Collection: Ensure borrower has sufficient balance for repayment + fee
Reference Implementation
~/work/lux/standard/contracts/tokens/LRC20/LRC20FlashMint.sol
Related LPs
- LP-3020: LRC-20 Fungible Token Standard (base)
- LP-3156: LRC-3156 Flash Loans (interface standard)
Document Maintainer: Lux Industries Last Updated: 2025-12-25