Integrations

Third-Party Integrations

This guide is aimed at front-end and smart-contract developers that want to add rovBTC support to their dApps, dashboards or automated strategies.

All code samples use the Botanix test-net RPC and the ethers v6 library, but the same concepts apply to other stacks.


1. Discover the contracts

Name
Address
Interface

rovBTC (ERC-4626)

0x9BC574a6f1170e90D80826D86a6126d59198A3Ef

IRovBTC

pBTC (ERC-20)

0x0D2437F93Fed6EA64Ef01cCde385FB1263910C56

IPBTC

stBTC (ERC-20)

0xF4586028FFdA7Eca636864F80f8a3f2589E33795

ISTBTC

Replace the placeholders with the network-specific addresses published by the Rover team.

export const ROV_BTC = "0x…";
export const P_BTC  = "0x…";
export const ST_BTC = "0x…";

2. Reading data (balance, TVL, previews)

import { Contract, JsonRpcProvider, parseUnits, formatUnits } from "ethers";
import { ROV_BTC } from "./const";
import rovBTCAbi from "./abi/rovBTC.json";

const provider = new JsonRpcProvider("https://testnet.botanix.io");
const rovBTC = new Contract(ROV_BTC, rovBTCAbi, provider);

export async function getUserInfo(user: string) {
  const [shares, previewRedeem] = await Promise.all([
    rovBTC.balanceOf(user),
    rovBTC.previewRedeem(parseUnits("1", 18)) // 1 rovBTC → pBTC
  ]);

  const tvl = await rovBTC.totalAssets();

  return {
    shares: formatUnits(shares, 18),
    oneShareWorth: formatUnits(previewRedeem, 18),
    tvl: formatUnits(tvl, 18)
  };
}

The same helpers (previewDeposit, previewWithdraw, calculateTVL) are available and gas-cheap because they are view functions.


3. Staking from your UI (front-end)

3.1 Deposit native BTC

import { BrowserProvider, parseUnits } from "ethers";
import rovBTCAbi from "./abi/rovBTC.json";
import { ROV_BTC } from "./const";

export async function depositNativeBTC(amountBtc: string, referralId = 0) {
  const provider = new BrowserProvider(window.ethereum!);
  const signer   = await provider.getSigner();
  const rovBTC   = new Contract(ROV_BTC, rovBTCAbi, signer);

  const tx = await rovBTC.depositBTC(
    parseUnits(amountBtc, 18),   // assets argument (pBTC precision)
    await signer.getAddress(),   // receiver
    referralId,
    {
      value: parseUnits(amountBtc, 18) // msg.value = native BTC sent
    }
  );
  await tx.wait();
}

3.2 Deposit pBTC

import pBTCAbi from "./abi/pBTC.json";
import { P_BTC } from "./const";

export async function depositPBTC(amount: string, referralId = 0) {
  const provider = new BrowserProvider(window.ethereum!);
  const signer   = await provider.getSigner();

  // 1️⃣ Approve pBTC
  const pBTC = new Contract(P_BTC, pBTCAbi, signer);
  await (await pBTC.approve(ROV_BTC, parseUnits(amount, 18))).wait();

  // 2️⃣ Deposit
  const rovBTC = new Contract(ROV_BTC, rovBTCAbi, signer);
  await (await rovBTC.depositPBTC(parseUnits(amount, 18), await signer.getAddress(), referralId)).wait();
}

3.3 Deposit stBTC

import stBTCAbi from "./abi/stBTC.json";
import { ST_BTC } from "./const";

export async function depositStBTC(amount: string, referralId = 0) {
  const provider = new BrowserProvider(window.ethereum!);
  const signer   = await provider.getSigner();
  const stBTC    = new Contract(ST_BTC, stBTCAbi, signer);

  await (await stBTC.approve(ROV_BTC, parseUnits(amount, 18))).wait();

  const rovBTC = new Contract(ROV_BTC, rovBTCAbi, signer);
  await (await rovBTC.depositStakedBTC(parseUnits(amount, 18), await signer.getAddress(), referralId)).wait();
}

From your component you can call any of the above helpers depending on the asset type detected in the user's wallet.


4. Programmatic deposits (scripts & bots)

Below is a TypeScript Hardhat script that periodically moves idle pBTC from a treasury address into the vault.

import { ethers } from "hardhat";
import rovBTCAbi from "../abi/rovBTC.json";
import pBTCAbi from "../abi/pBTC.json";
import { ROV_BTC, P_BTC } from "../const";

async function main() {
  const signer = (await ethers.getSigners())[0]; // eg. Cold-wallet relayer

  const pBTC  = new ethers.Contract(P_BTC, pBTCAbi, signer);
  const rovBTC = new ethers.Contract(ROV_BTC, rovBTCAbi, signer);

  const amount = await pBTC.balanceOf(signer.address);
  if (amount.isZero()) return console.log("Nothing to deposit");

  await (await pBTC.approve(ROV_BTC, amount)).wait();
  await (await rovBTC.depositPBTC(amount, signer.address, 0)).wait();

  console.log(`Deposited ${ethers.formatUnits(amount, 18)} pBTC`);
}

main().catch(console.error);

5. On-chain integrations (Solidity)

Your contract can stake treasury assets or build strategies on top of rovBTC. Import the minimal interface and interact just like any ERC-4626.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IRovBTC {
    function depositPBTC(uint256 assets, address receiver, uint256 referralId) external returns (uint256 shares);
}

contract RovBTCTreasury {
    address public immutable ROV_BTC;

    constructor(address _rovBtc) {
        ROV_BTC = _rovBtc;
    }

    // The contract must already hold pBTC (e.g. via fees)
    function stake(uint256 amount) external {
        IRovBTC(ROV_BTC).depositPBTC(amount, address(this), 0);
    }
}

Because rovBTC follows the ERC-4626 token standard you can plug it into any yield aggregator that supports the interface without additional wrappers.


6. Test-net faucet

Need pBTC or stBTC to test your integration? Use the public faucet:

  1. Visit https://faucet.botanix.io.

  2. Claim test BTC, swap it for pBTC at https://swap.botanix.io.

  3. Stake pBTC into stBTC at https://stake.botanix.io (optional).


7. Support

For technical questions join our Discord or open a GitHub discussion.

Last updated