UniswapFlashswapDirectMintHandlerWithDust

Git Source

Inherits: IonHandlerBase, IUniswapV3SwapCallback

This contract is forked off of the UniswapFlashswapDirectMintHandler, with one distinction that it handles potential dust collateral amounts that can accrue when the contract ends up minting more collateral than originally intended. This situation can occur when the user has a desired leverage amount and thus an exact resulting collateral amount, but due to rounding errors in the minting contract, the handler is forced to mint a dust amount more than the desired collateral amount. In this contract, the dust is added to the total final deposit amount and ends up in the user's vault as additional collateral. The key difference between this contract and UniswapFlashswapDirectMintHandler is a relaxed bound in comparing the sum of initial user deposit and additionally minted collateral to the caller's requested resulting additional collateral amount. This contract allows for easy creation of leverage positions through a Uniswap flashswap and direct mint of the collateral from the provider. This will be used when the collateral cannot be minted directly with the base asset but can be directly minted by a token that the base asset has a UniswapV3 pool with. This contract is to be used when there exists a UniswapV3 pool between the base asset and the mint asset.

State Variables

MIN_SQRT_RATIO

The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)

uint160 internal constant MIN_SQRT_RATIO = 4_295_128_739;

MAX_SQRT_RATIO

The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)

uint160 internal constant MAX_SQRT_RATIO = 1_461_446_703_485_210_103_287_273_052_203_988_822_378_723_970_342;

UNISWAP_POOL

IUniswapV3Pool public immutable UNISWAP_POOL;

MINT_ASSET

IERC20 public immutable MINT_ASSET;

MINT_IS_TOKEN0

bool private immutable MINT_IS_TOKEN0;

Functions

constructor

Creates a new UniswapFlashswapDirectMintHandler instance.

constructor(IUniswapV3Pool _uniswapPool, IERC20 _mintAsset);

Parameters

Name
Type
Description

_uniswapPool

IUniswapV3Pool

Pool to perform the flashswap on.

_mintAsset

IERC20

The asset used to mint the collateral.

flashswapAndMint

Transfer collateral from user -> Initiate flashswap between from base asset to mint asset -> Use the mint asset to mint the collateral -> Deposit all collateral into IonPool -> Borrow the base asset -> Close the flashswap by sending the base asset to the Uniswap pool.

function flashswapAndMint(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt,
    uint256 deadline,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof)
    checkDeadline(deadline);

Parameters

Name
Type
Description

initialDeposit

uint256

in collateral terms. [WAD]

resultingAdditionalCollateral

uint256

in collateral terms. [WAD]

maxResultingDebt

uint256

in base asset terms. [WAD]

deadline

uint256

The unix timestamp after which the uniswap transaction reverts.

proof

bytes32[]

used to validate the user is whitelisted.

_flashswapAndMint

function _flashswapAndMint(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt
)
    internal;

_initiateFlashSwap

Handles swap initiation logic. This function can only initiate exact output swaps.

function _initiateFlashSwap(
    bool zeroForOne,
    uint256 amountOut,
    address recipient,
    bytes memory data
)
    private
    returns (uint256 amountIn);

Parameters

Name
Type
Description

zeroForOne

bool

Direction of the swap.

amountOut

uint256

Desired amount of output.

recipient

address

of output tokens.

data

bytes

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.

function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external override;

Parameters

Name
Type
Description

amount0Delta

int256

change in token0

amount1Delta

int256

change in token1

_data

bytes

arbitrary data

_mintCollateralAsset

Deposits the mint asset into the provider's collateral-asset deposit contract.

function _mintCollateralAsset(uint256 amountMintAsset) internal virtual returns (uint256);

Parameters

Name
Type
Description

amountMintAsset

uint256

amount of "mint asset" to deposit. [WAD]

Returns

Name
Type
Description

<none>

uint256

Amount of collateral asset received. [WAD]

_getAmountInForCollateralAmountOut

Calculates the amount of mint asset required to receive amountLrt.

Calculates the amount of mint asset required to receive amountLrt.

function _getAmountInForCollateralAmountOut(uint256 amountLrt) internal view virtual returns (uint256);

Parameters

Name
Type
Description

amountLrt

uint256

Desired output amount. [WAD]

Returns

Name
Type
Description

<none>

uint256

Amount mint asset required for desired output. [WAD]

Errors

InvalidUniswapPool

error InvalidUniswapPool();

InvalidZeroLiquidityRegionSwap

error InvalidZeroLiquidityRegionSwap();

CallbackOnlyCallableByPool

error CallbackOnlyCallableByPool(address unauthorizedCaller);

OutputAmountNotReceived

error OutputAmountNotReceived(uint256 amountReceived, uint256 amountRequired);