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
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 areview
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:
Visit
https://faucet.botanix.io
.Claim test BTC, swap it for pBTC at
https://swap.botanix.io
.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