Zap from a different chain

Deposit any token from any chain into any strategies in a single transaction

We leverage deBridge’s DLN Protocol to bridge tokens directly into our provided strategies on DogBone. This requires a payload passed by the Maker for the Taker to execute on the destination (in this case, the Sonic blockchain). deBridge supports this functionality by introducing Hook Data. Specifically, deBridge’s Hook Data requires a HookPayload structured as follows:

struct UniversalHookPayload {
    address to;
    uint32 txGas;
    bytes callData;
}

The to address is set to our Zap Smart Contract, while callData is the encoded representation of a Strategy.


struct Strategy {
    address strategy;         // The vault to deposit into
    address underlyingToken;  // The token required for deposit
    uint256 amountToDeposit;  // The amount of underlying token to deposit
    address lpReceiver;       // The receiver of LP tokens
    bytes4 funcSelector;      // Determines which function to call based on the type of strategy
    bytes loopingStrategy;    // Empty if not a looping strategy; otherwise, it contains the encoded data for SiloLoopingStrategy/AaveLoopingStrategy
}


struct SiloLoopingStrategy {
    bool isVaultProtected;    // Indicates if the Silo’s vault is non-borrowable
    uint256 leverage;         // Leverage of the position
    uint256 flashAmount;      // Amount of the borrow token to flash loan from the Silo Borrow vault
    bytes swapFlashloanData;  // Swap data to convert the borrow token into the deposit token, encoded per the Swap struct
}


struct Swap {
    address fromToken;
    uint256 fromAmount;
    address dexAggregatorRouter;
    bytes data;
    uint256 value;
}

The setter will then execute one of the following functions on our Zap Smart Contract when sending tokens (either onEtherReceived or onERC20Received). These functions will subsequently call the doStrategy function, which deposits the received tokens directly into the destination strategy.

function onEtherReceived(bytes32, address, bytes memory _payload)
        external
        payable
        returns (bool callSucceeded, bytes memory callResult)
{
    DlnExternalCallLib.ExternalCallPayload memory payload =
        abi.decode(_payload, (DlnExternalCallLib.ExternalCallPayload));
    (callSucceeded, callResult) = address(payload.to).call(payload.callData);
}

function onERC20Received(
    bytes32,
    address _token,
    uint256 _transferredAmount,
    address _fallbackAddress,
    bytes memory _payload
) external returns (bool callSucceeded, bytes memory callResult) {
    uint256 tokenBal = IERC20(_token).balanceOf(address(this));
    assert(_transferredAmount <= tokenBal);
    DlnExternalCallLib.ExternalCallPayload memory payload =
        abi.decode(_payload, (DlnExternalCallLib.ExternalCallPayload));
    (callSucceeded, callResult) = address(payload.to).call(payload.callData);
    tokenBal = IERC20(_token).balanceOf(address(this));
    if (tokenBal > 0 && _fallbackAddress != address(0)) IERC20(_token).transfer(_fallbackAddress, tokenBal);
}

/// API for all strategy zaps
/// @param T strategy Data
function doStrategy(Strategy memory T) public payable returns (bytes memory);

Last updated