Flash Swaps
⚡ Flash Swaps on Zealous Swap
Flash swaps are a native feature of Zealous Swap pairs. All swaps, under the hood, are flash swaps — meaning tokens are sent before the pair enforces repayment. Thanks to atomic transactions on the blockchain, the entire operation can be safely reverted if repayment conditions are not met.
This allows for powerful use cases like arbitrage, liquidations, or cross-protocol logic — all without upfront capital.
🧠 How Flash Swaps Work
The swap function in a Zealous Swap pair looks like this:
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data,
address actualUser
) external;If you call swap() with a non-empty data field, the pair assumes you're doing a flash swap and sends the tokens before collecting payment.
It then invokes a callback on the recipient address:
function zealousSwapCall(address sender, uint amount0, uint amount1, bytes calldata data) external;Your contract receives the tokens, performs any logic (e.g., arbitrage, on-chain liquidation, flash loan interaction), and must repay the correct amount within the same transaction.
🔄 Example: Flash Swap USDT, Return WKAS
Let’s say the USDT/WKAS pool has USDT as token0 and WKAS as token1.
You call:
pair.swap(
1000e6, // amount0Out: 1000 USDT
0, // amount1Out: 0 WKAS
address(this),
abi.encode(someData), // triggers flash logic
address(this)
);The pair sends 1000 USDT to your contract, then calls:
function zealousSwapCall(address sender, uint amount0, uint amount1, bytes calldata data)Inside that function, you might:
Use the USDT in a lending protocol.
Swap borrowed assets for WKAS.
Repay the USDT flash loan (plus fee) to the pair.
✅ Required Checks in zealousSwapCall
zealousSwapCallAlways ensure:
function zealousSwapCall(address sender, uint amount0, uint amount1, bytes calldata data) external {
address token0 = IZealousPair(msg.sender).token0();
address token1 = IZealousPair(msg.sender).token1();
address expectedPair = IZealousFactory(factory).getPair(token0, token1);
require(msg.sender == expectedPair, "Unauthorized caller");
// ... your logic goes here
}This prevents spoofing or unexpected callbacks.
💸 Flash Swap Repayment Rules
At the end of your function, the pair must receive enough tokens to satisfy the invariant, accounting for the pair swap fee (let's assume 0.3%).
If you're returning the same token:
returnedAmount >= withdrawnAmount / 0.997;This reflects the effective ~0.3009% fee applied on the output.
If you're returning a different token:
Use the router's getAmountIn() function to calculate how much of token B must be returned for token A withdrawn. This mirrors a typical swap calculation.
🧰 Flash Swap Interface
To use flash swaps, implement this interface:
pragma solidity >=0.5.0;
interface IZealousSwapCallee {
function zealousSwapCall(address sender, uint amount0, uint amount1, bytes calldata data) external;
}The pair will call this function automatically during the swap if the data field is non-empty.
🛠 Practical Use Cases
Arbitrage across different DEXes
Leveraged liquidity provisioning
Flash collateralized borrowing
Liquidations and collateral swaps
No upfront funds are needed — as long as you repay the flash loan (with fee) within the same transaction.
✅ Summary
Flash swaps allow token withdrawal before repayment.
The recipient must implement
zealousSwapCalland return enough tokens.The operation reverts if repayment fails — no partial execution.
Enables capital-efficient DeFi strategies without trust assumptions.
Last updated