> ## Documentation Index
> Fetch the complete documentation index at: https://distributedcrafts.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# DeFi Strategies

> Build 1-click DeFi actions with custom strategies, multicall, and cross-chain execution

## Overview

BOB Gateway enables users to interact with DeFi protocols using a single Bitcoin transaction. There are three integration approaches:

<CardGroup cols={3}>
  <Card title="Custom Strategy" icon="code">
    Full control with smart contracts
  </Card>

  <Card title="Multicall" icon="list-check">
    No deployment needed
  </Card>

  <Card title="Cross-Chain" icon="arrows-split-up-and-left">
    Execute on destination chains
  </Card>
</CardGroup>

## Which Approach Should I Choose?

<AccordionGroup>
  <Accordion icon="code" title="Custom Strategy - For Complex Logic">
    Choose this when you need:

    * Complex multi-step operations
    * Gas optimization
    * Custom events and logging
    * Full control over execution flow
    * State management in your contract
  </Accordion>

  <Accordion icon="list-check" title="Multicall - For Quick Integration">
    Choose this when you want to:

    * Integrate with existing contracts on BOB
    * Avoid deploying new contracts
    * Implement simple approve + deposit patterns
    * Get started quickly
  </Accordion>

  <Accordion icon="arrows-split-up-and-left" title="Cross-Chain - For LayerZero Bridges">
    Choose this for:

    * Bridging to Ethereum, Base, or other LayerZero chains
    * Executing actions on destination chain after bridge
    * Depositing into lending protocols on destination
    * Multi-step operations post-bridge
  </Accordion>
</AccordionGroup>

***

## Option 1: Custom Strategy Contract

Deploy a smart contract that implements the Gateway strategy interface for full control.

### Strategy Interface

```solidity theme={null}
interface IStrategy {
    function handleGatewayMessage(
        IERC20 tokenSent,    // Wrapped BTC token (WBTC, tBTC, etc.)
        uint256 amountIn,    // Amount received
        address recipient,   // User's EVM address
        bytes memory message // Optional parameters
    ) external;
}
```

### Complete Example: Convert to SolvBTC

```solidity theme={null}
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

interface ISolvBTCRouter {
    function deposit(
        address targetToken_,
        address currency_,
        uint256 currencyAmount_,
        uint256 minimumTargetTokenAmount_,
        uint64 expireTime_
    ) external returns (uint256);
}

contract SolvBTCStrategy {
    using SafeERC20 for IERC20;

    ISolvBTCRouter public immutable solvBTCRouter;
    IERC20 public immutable solvBTC;

    constructor(address _solvBTCRouter, address _solvBTC) {
        solvBTCRouter = ISolvBTCRouter(_solvBTCRouter);
        solvBTC = IERC20(_solvBTC);
    }

    function handleGatewayMessage(
        IERC20 tokenSent,
        uint256 amountIn,
        address recipient,
        bytes memory message
    ) external {
        // Transfer wrapped BTC from Gateway
        tokenSent.safeTransferFrom(msg.sender, address(this), amountIn);

        // Decode minimum output from message (optional)
        uint256 minOutput = message.length > 0 
            ? abi.decode(message, (uint256)) 
            : 0;

        // Approve SolvBTC router
        tokenSent.safeIncreaseAllowance(address(solvBTCRouter), amountIn);

        // Convert to SolvBTC
        uint256 solvBTCAmount = solvBTCRouter.deposit(
            address(solvBTC), 
            address(tokenSent), 
            amountIn, 
            minOutput,
            uint64(block.timestamp + 1)
        );

        // Send SolvBTC to user
        solvBTC.safeTransfer(recipient, solvBTCAmount);
    }
}
```

### Using Your Custom Strategy

```typescript theme={null}
import { GatewaySDK, parseBtc } from '@gobob/bob-sdk';

const gatewaySDK = new GatewaySDK();

// Encode minimum output parameter
const minOutput = parseUnits("0.099", 8); // Minimum 0.099 BTC worth
const message = encodeAbiParameters(
  [{ type: 'uint256' }],
  [minOutput]
);

const quote = await gatewaySDK.getQuote({
  fromChain: 'bitcoin',
  fromToken: '0x0000000000000000000000000000000000000000',
  toChain: 'bob',
  toToken: '0xYourStrategyAddress', // Your deployed strategy
  fromUserAddress: 'bc1q...',
  toUserAddress: '0x...', // Receives the SolvBTC
  amount: parseBtc("0.1"),
  strategyMessage: message, // Optional parameters
});
```

<Note>
  The `toToken` parameter should be set to your deployed strategy contract address. Optionally, use `strategyAddress` for advanced cases where the strategy target differs from the token destination. The `strategyMessage` parameter passes ABI-encoded parameters to your strategy's `handleGatewayMessage` function.
</Note>

***

## Option 2: Multicall Strategy

Execute multiple contract calls without deploying custom contracts.

### Basic Approve + Deposit Pattern

```typescript theme={null}
import { 
  encodeFunctionData, 
  parseAbi, 
  encodeAbiParameters, 
  parseAbiParameters,
  Address 
} from 'viem';
import { GatewaySDK, parseBtc } from '@gobob/bob-sdk';

const WBTC_ADDRESS = '0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3'; // BOB mainnet
const PROTOCOL_ADDRESS = '0xYourProtocolAddress';

function generateMulticallMessage(
  userAddress: Address, 
  depositAmount: bigint
) {
  // Step 1: Approve protocol to spend WBTC
  const approveCall = encodeFunctionData({
    abi: parseAbi(['function approve(address spender, uint256 value)']),
    functionName: 'approve',
    args: [PROTOCOL_ADDRESS, depositAmount],
  });

  // Step 2: Deposit into protocol
  const depositCall = encodeFunctionData({
    abi: parseAbi(['function deposit(address asset, uint256 amount, address onBehalfOf)']),
    functionName: 'deposit',
    args: [WBTC_ADDRESS, depositAmount, userAddress],
  });

  // Encode as multicall message
  return encodeAbiParameters(
    parseAbiParameters('((address target, bytes callData, uint256 value)[], address fallbackRecipient)'),
    [
      [
        [
          { target: WBTC_ADDRESS, callData: approveCall, value: 0n },
          { target: PROTOCOL_ADDRESS, callData: depositCall, value: 0n },
        ],
        userAddress, // Fallback recipient if execution fails
      ],
    ]
  );
}

// Get quote with multicall
const depositAmount = parseBtc("0.1");
const multicallMessage = generateMulticallMessage(userAddress, depositAmount);

const quote = await gatewaySDK.getQuote({
  fromChain: 'bitcoin',
  fromToken: '0x0000000000000000000000000000000000000000',
  toChain: 'bob',
  toToken: '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c',
  fromUserAddress: 'bc1q...',
  toUserAddress: userAddress,
  amount: depositAmount,
  strategyMessage: multicallMessage,
});
```

### Advanced: Multi-Protocol Interaction

```typescript theme={null}
function generateComplexMulticall(user: Address, amount: bigint) {
  const calls = [
    // 1. Approve DEX router
    {
      target: WBTC_ADDRESS,
      callData: encodeFunctionData({
        abi: erc20Abi,
        functionName: 'approve',
        args: [DEX_ROUTER, amount / 2n],
      }),
      value: 0n,
    },
    // 2. Swap half to another token
    {
      target: DEX_ROUTER,
      callData: encodeFunctionData({
        abi: parseAbi(['function swapExactTokensForTokens(...)']),
        functionName: 'swapExactTokensForTokens',
        args: [/* swap params */],
      }),
      value: 0n,
    },
    // 3. Add liquidity
    {
      target: DEX_ROUTER,
      callData: encodeFunctionData({
        abi: parseAbi(['function addLiquidity(...)']),
        functionName: 'addLiquidity',
        args: [/* liquidity params */],
      }),
      value: 0n,
    },
  ];

  return encodeAbiParameters(
    parseAbiParameters('((address target, bytes callData, uint256 value)[], address fallbackRecipient)'),
    [[calls, user]]
  );
}
```

***

## Option 3: Cross-Chain Destination Calls

Cross-Chain Destination Calls allow you to execute arbitrary smart contract calls on the destination chain as part of a cross-chain swap or bridge transaction. This is ideal for advanced integrations, multi-step DeFi actions, or custom workflows triggered by a cross-chain transfer.

### How It Works

When you request a quote (via `get-quote`), you can specify a message containing an ABI-encoded vector of calls. Each call uses the following Solidity struct:

```solidity theme={null}
struct Call {
  address target;
  bytes callData;
  uint256 value;
}
```

* `target`: Contract address to call on the destination chain
* `callData`: ABI-encoded function call data
* `value`: Amount of native token (e.g., ETH) to send with the call

Encode a vector of these `Call` structs using standard Solidity ABI encoding and include it in the `strategyMessage` field of your quote request.

On the destination chain, the solver decodes the vector and executes each call using a LayerZero (L0) composer contract. This ensures atomic execution and proper sequencing of all calls.

#### SDK Example: Sending Cross-Chain Calls

```typescript theme={null}
import { encodeAbiParameters, parseAbiParameters, encodeFunctionData, Address } from 'viem';
import { GatewaySDK, parseBtc } from '@gobob/bob-sdk';

const gatewaySDK = new GatewaySDK();

// Example: Call two contracts on destination chain
const TARGET1 = '0xTargetContract1';
const TARGET2 = '0xTargetContract2';
const userAddress = '0xUserAddress';

// Prepare call data for each target
const call1 = {
  target: TARGET1,
  callData: encodeFunctionData({
    abi: [{ type: 'function', name: 'doSomething', inputs: [{ name: 'amount', type: 'uint256' }] }],
    functionName: 'doSomething',
    args: [12345n],
  }),
  value: 0n,
};

const call2 = {
  target: TARGET2,
  callData: encodeFunctionData({
    abi: [{ type: 'function', name: 'notify', inputs: [{ name: 'user', type: 'address' }] }],
    functionName: 'notify',
    args: [userAddress],
  }),
  value: 0n,
};

// ABI encode the vector of calls
const crossChainMessage = encodeAbiParameters(
  parseAbiParameters('(address target, bytes callData, uint256 value)[]'),
  [[call1, call2]]
);

// Request a quote with the cross-chain message
const quote = await gatewaySDK.getQuote({
  fromChain: 'bitcoin',
  fromToken: '0x0000000000000000000000000000000000000000',
  toChain: 'ethereum', // or other destination chain
  toToken: '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c',
  fromUserAddress: 'bc1q...',
  toUserAddress: userAddress,
  amount: parseBtc('0.1'),
  strategyMessage: crossChainMessage,
});
```

#### Benefits

* Enables complex workflows and contract interactions as part of a cross-chain swap
* Ensures atomic execution via the L0 composer

> **Note:** Make sure all target contracts and call data are valid for the destination chain. The composer contract handles sequencing and error management; failed calls may revert the entire batch depending on configuration.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Integration Guide" icon="code" href="/gateway/integration">
    Complete SDK integration walkthrough
  </Card>

  <Card title="Bitcoin Wallets" icon="wallet" href="/gateway/wallets">
    Implement Bitcoin wallet support
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/overview">
    Complete API documentation
  </Card>

  <Card title="GitHub Examples" icon="github" href="https://github.com/bob-collective/bob/tree/master/sdk/examples">
    View example implementations
  </Card>
</CardGroup>
