On-Chain Actions
Introductionโ
BOB Gateway allows Bitcoin users to interact with DeFi protocols using a single Bitcoin transaction. There are two ways to integrate:
- Custom Strategy Contract - Implement a smart contract that receives wrapped BTC and executes your protocol logic
- Multicall Integration - Use the built-in multicall handler to interact with existing contracts without deploying new ones
Gateway Overview
For a detailed explanation of Gateway's architecture and user flow, see the technical overview.
Which approach should I choose - Custom Strategy or Multicall?
- Custom Strategy: Choose this if you need complex logic, gas optimization, custom events, or want full control over the execution flow
- Multicall: Choose this if you want to integrate with existing contracts without deploying new ones, or for simple approve + deposit patterns
Option 1: Custom Strategy Contractโ
Deploy a smart contract that implements the Gateway strategy interface. This gives you full control over the logic and allows for complex multi-step operations.
Strategy Interfaceโ
Implement this interface in your contract:
interface IStrategy {
function handleGatewayMessage(
IERC20 tokenSent, // The wrapped BTC token (e.g., WBTC, tBTC)
uint256 amountIn, // Amount of wrapped BTC received
address recipient, // User's EVM address for receiving output tokens
bytes memory message // Optional parameters from the user
) external;
}
Complete Strategy Exampleโ
Here's a full implementation that converts WBTC to SolvBTC:
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);
// Approve SolvBTC router
tokenSent.safeIncreaseAllowance(address(solvBTCRouter), amountIn);
// Convert to SolvBTC
uint256 solvBTCAmount = solvBTCRouter.deposit(
address(solvBTC),
address(tokenSent),
amountIn,
minOutput: 0,
uint64(block.timestamp + 1)
);
// Send SolvBTC to user
solvBTC.safeTransfer(recipient, solvBTCAmount);
}
}