CenturionDEX
Launch App

Calling Flash

Last modified:

Parameter structs

Two structs capture the data the contract needs: one for the external entry point and one to carry context into the callback.

FlashParams holds the token addresses and amounts to borrow, plus three fee tiers — fee1 identifies the pool we borrow from; fee2 and fee3 identify the two pools we swap through during the callback.

  struct FlashParams {
        address token0;
        address token1;
        uint24 fee1;
        uint256 amount0;
        uint256 amount1;
        uint24 fee2;
        uint24 fee3;
    }

FlashCallbackData is ABI-encoded into the data argument of flash and decoded inside the callback. It includes a poolKey — the sorted token pair plus fee tier — returned by the PoolAddress library, along with the two alternate fee tiers and the address that should receive any profit.

    struct FlashCallbackData {
        uint256 amount0;
        uint256 amount1;
        address payer;
        PoolAddress.PoolKey poolKey;
        uint24 poolFee2;
        uint24 poolFee3;
    }

Computing the pool address

initFlash begins by assembling a PoolKey from the caller-supplied parameters. The key is then passed to PoolAddress.computeAddress to derive the deterministic pool address — no on-chain lookup required.

    function initFlash(FlashParams memory params) external {
        PoolAddress.PoolKey memory poolKey =
            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee1});

Cast the computed address to ICenturionV3Pool so we can call flash:

        ICenturionV3Pool pool = ICenturionV3Pool(PoolAddress.computeAddress(factory, poolKey));

Calling flash

Finally, call flash on the pool. The last argument ABI-encodes FlashCallbackData, which the pool passes straight through to centurionV3FlashCallback. Inside the callback (covered in the next section) the contract decodes this struct to know what to swap and whom to pay.

        pool.flash(
            address(this),
            params.amount0,
            params.amount1,
            abi.encode(
                FlashCallbackData({
                    amount0: params.amount0,
                    amount1: params.amount1,
                    payer: msg.sender,
                    poolKey: poolKey,
                    poolFee2: params.fee2,
                    poolFee3: params.fee3
                })
            )
        );

Full function

    //fee1 is the fee of the pool from the initial borrow
    //fee2 is the fee of the first pool to arb from
    //fee3 is the fee of the second pool to arb from
    struct FlashParams {
        address token0;
        address token1;
        uint24 fee1;
        uint256 amount0;
        uint256 amount1;
        uint24 fee2;
        uint24 fee3;
    }
 
    // fee2 and fee3 are the two other fees associated with the two other pools of token0 and token1
    struct FlashCallbackData {
        uint256 amount0;
        uint256 amount1;
        address payer;
        PoolAddress.PoolKey poolKey;
        uint24 poolFee2;
        uint24 poolFee3;
    }
 
function initFlash(FlashParams memory params) external {
        PoolAddress.PoolKey memory poolKey =
            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee1});
        ICenturionV3Pool pool = ICenturionV3Pool(PoolAddress.computeAddress(factory, poolKey));
        pool.flash(
            address(this),
            params.amount0,
            params.amount1,
            abi.encode(
                FlashCallbackData({
                    amount0: params.amount0,
                    amount1: params.amount1,
                    payer: msg.sender,
                    poolKey: poolKey,
                    poolFee2: params.fee2,
                    poolFee3: params.fee3
                })
            )
        );
    }