UniswapFlashswapHandler
Inherits: IonHandlerBase, IUniswapV3SwapCallback
This contract allows for easy creation and closing of leverage positions through Uniswap flashswaps--flashloan not necessary! In terms of creation, this may be a more desirable path than directly minting from an LST provider since market prices tend to be slightly lower than provider exchange rates. DEXes also provide an avenue for atomic deleveraging since the LST -> ETH exchange can be made.
When using the UniswapFlashSwapHandler
, the IUniswapV3Pool pool
fed to the constructor should be the WETH/[LST] pool. Unlike Balancer flashloans, there is no concern here that somebody else could initiate a flashswap, then direct the callback to be called on this contract. Uniswap enforces that callback is only called on msg.sender
.
State Variables
MIN_SQRT_RATIO
The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
MAX_SQRT_RATIO
The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
UNISWAP_POOL
WETH_IS_TOKEN0
Functions
constructor
Creates a new UniswapFlashswapHandler
instance.
Parameters
_pool
IUniswapV3Pool
Pool to perform the flashswap on.
_wethIsToken0
bool
Whether WETH is token0 or token1 in the pool.
flashswapLeverage
Transfer collateral from user -> initiate swap for collateral from WETH on Uniswap (contract will receive collateral first) -> deposit all collateral into IonPool
-> borrow WETH from IonPool
-> complete swap by sending WETH to Uniswap.
Parameters
initialDeposit
uint256
in collateral terms. [WAD]
resultingAdditionalCollateral
uint256
in collateral terms. [WAD]
maxResultingAdditionalDebt
uint256
in WETH terms. This value also allows the user to control slippage of the swap. [WAD]
sqrtPriceLimitX96
uint160
for the swap. Recommended value is the current exchange rate to ensure the swap never costs more than a direct mint would. Passing the current exchange rate means swapping beyond that point is worse than direct minting.
deadline
uint256
timestamp for which the transaction must be executed. This prevents txs that have sat in the mempool for too long to be executed.
proof
bytes32[]
that the user is whitelisted.
_flashswapLeverage
Parameters
initialDeposit
uint256
in terms of swETH
resultingAdditionalCollateral
uint256
in terms of swETH. How much collateral to add to the position in the vault.
maxResultingAdditionalDebt
uint256
in terms of WETH. How much debt to add to the position in the vault.
sqrtPriceLimitX96
uint160
for the swap. Recommended value is the current exchange rate to ensure the swap never costs more than a direct mint would.
flashswapDeleverage
Initiate swap for WETH from collateral (contract will receive WETH first) -> repay debt on IonPool
-> withdraw (and gem-exit) collateral from IonPool
-> complete swap by sending collateral to Uniswap.
The two function parameters must be chosen carefully. If maxCollateralToRemove
's ETH valuation were higher then debtToRemove
, it would theoretically be possible to sell more collateral then was required for debtToRemove
to be repaid (even if debtToRemove
is worth nowhere near that valuation) due to the slippage of the sell. maxCollateralToRemove
is essentially a slippage guard here.
Parameters
maxCollateralToRemove
uint256
he max amount of collateral user is willing to sell to repay debtToRemove
debt. [WAD]
debtToRemove
uint256
The desired amount of debt to remove. [WAD]
sqrtPriceLimitX96
uint160
for the swap. Can be set to 0 to set max bounds.
deadline
uint256
_initiateFlashSwap
Handles swap initiation logic. This function can only initiate exact output swaps.
Parameters
zeroForOne
bool
Direction of the swap.
amountOut
uint256
Desired amount of output.
recipient
address
of output tokens.
sqrtPriceLimitX96
uint160
of the swap.
data
FlashSwapData
Arbitrary data to be passed through swap callback.
uniswapV3SwapCallback
From the perspective of the pool i.e. Negative amount means pool is sending. This function is intended to never be called directly. It should only be called by the Uniswap pool during a swap initiated by this contract.
One thing to note from a security perspective is that the pool only calls the callback on msg.sender
. So a theoretical attacker cannot call this function by directing where to call the callback.
Parameters
amount0Delta
int256
change in token0
amount1Delta
int256
change in token1
_data
bytes
arbitrary data