Get a list of all the Baults, their TVL and APY here:
Bault Compounding Guide
This guide explains how compounding works in Baults, including the BGT auction mechanism, optimal usage patterns, and integration with the BountyHelper contract which is designed to make compounding free and effectively available for anyone to call.
How Compounding Works
Baults are ERC4626-compliant vaults that stake tokens in reward vaults to earn BGT rewards. Over time, these BGT rewards accumulate but remain unclaimed in the reward vault. Compounding is the process of claiming these BGT rewards and either:
Receiving them directly as BGT tokens
Converting them to wrapped BGT tokens (like iBGT, yBGT, LBGT etc.)
The Bounty Mechanism
Baults use a bounty-based auction system that:
Allows anyone to trigger the compounding process
Requires the caller to provide the configured "bounty" in bault asset (the staking tokens)
Gives the caller all the accumulated BGT rewards as either BGT or wrappedBGT of choice.
How the Bounty System Works
The caller pays a fixed amount of staking tokens (the bounty)
A small portion of the bounty (set by compoundFeeBps) goes to the protocol treasury
The rest of the bounty is staked in the reward vault, benefiting all vault users effectively increasing the share price for each user.
The caller receives all accumulated BGT rewards or a wrapped version
This creates a market-driven incentive for compounding - when the value of unclaimed BGT exceeds the bounty cost, someone will claim it.
This is a significant improvement over traditional compounding methods where the rewards are claimed and swapped for the asset, which can lead to slippage and loss of value while compounding. Additionally the swap system requires gatekeeping the compounding process and integration of swap routers for effective and secured compounding which limits the flexibility and accessibility of the compounding process.
The bounty system allows anyone to compound and benefit from the compounding process while also giving the bault users maximal compounding value.
Cost-Effective Compounding
With the introduction of the bounty system, you can benefit from the compounding process and claim the rewards. To compound cost-effectively:
Monitor BGT accrual: Wait until enough BGT has accumulated to justify the bounty cost
Calculate break-even point: Compare the value of claimable BGT against the bounty cost
Choose the right wrapper: Different wrappers have different valuations for BGT and are generally a better choice against BGT itself. So find the best wrapper that maximizes the value of the BGT rewards.
Executing Claims: Once the breakeven point has been reached, execute the claim transaction to receive the rewards as soon as possible to benefit from any excess rewards that accumulate.
Remember you are racing against other bots for the bounty, so act quickly while keeping a minimal profit margin to claim the rewards before someone else does.
Previewing Potential Claims
Before executing a compound transaction, you can preview the expected outcome:
// Preview the amount of BGT that would be claimed
uint256 bgtAmount = bault.earned();
// Preview the amount of wrapped BGT tokens that would be minted
uint256 wrappedAmount = bault.previewClaimBgtWrapper(wrapperAddress);
import { createPublicClient, http } from 'viem';
import { berachain } from 'viem/chains';
import { BAULT_ABI } from './abis'; // Import your ABI
const client = createPublicClient({
chain: berachain,
transport: http()
});
// Preview the amount of BGT that would be claimed
const earnedBgt = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'earned',
});
// Preview the amount of wrapped BGT tokens that would be minted
const wrappedAmount = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'previewClaimBgtWrapper',
args: [wrapperAddress],
});
const client = createPublicClient({
chain: berachain,
transport: http()
});
// Preview the amount of BGT that would be claimed
const earnedBgt = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'earned',
});
// Preview the amount of wrapped BGT tokens that would be minted
const wrappedAmount = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'previewClaimBgtWrapper',
args: [wrapperAddress],
});
Performing Compounding
Always correctly set the minAmountOut after previewing to ensure you do not get frontrun.
Direct BGT Claim
// Simple TypeScript with Viem - Direct BGT claim
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { berachain } from 'viem/chains';
import { BAULT_ABI, ERC20_ABI } from './abis';
// Setup account and client
const account = privateKeyToAccount(PRIVATE_KEY);
const client = createWalletClient({
account,
chain: berachain,
transport: http()
});
// Basic claim process
async function claimBgt(baultAddress) {
// 1. Get staking token and bounty
const stakingToken = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'stakingToken',
});
const bounty = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'bounty',
});
// 2. Approve the bounty transfer
await client.writeContract({
address: stakingToken,
abi: ERC20_ABI,
functionName: 'approve',
args: [baultAddress, bounty],
});
// 3. Preview the amount of BGT that would be claimed
// and make sure you pass it in as minAmountOut while claiming
// to avoid getting frontrun
const minAmountOut = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'earned',
});
// 4. Execute the claim
await client.writeContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'claimBgt',
args: [account.address, minAmountOut],
});
}
The BountyHelper is a specialized contract that enables anyone to compound Baults without needing the bounty payment upfront. It uses a clever mechanism to make compounding easy and accessible for everyone without need of the bounty.
How BountyHelper Works
Pre-funding mechanism: The helper maintains a balance of staking tokens that can be used for bounties
Swap integration: When using bounty helper, the claimed wrappers must be swapped for the staking token to return the bounty amount back to the contract. You can use any contract that can swap/exchange the bgtWrapper for the underlying staking token. We recommend using the Enso Router for swapping directly from the liquid wrapper to the underlying staking token.
Refund system: Returns any excess tokens to the caller after returning the free bounty amount accessed by the compounder and additionally rewards the compounder by transferring any amount of remaining staking token/bgt wrapper back to the user.
Compounding Algorithm Overview using the BountyHelper
The compounding process follows these key steps:
Discovery: Find baults that are ready to compound
Wrapper Selection: Determine the best BGT wrapper (iBGT, YBGT, LBGT) for maximum value
Quote Generation: Get swap quote to convert wrapper to underlying staking token
Profitability Check: Ensure the swap output covers the required bounty
Execution: Send the compound transaction via BountyHelper
Step 1: Check if Bault is Ready to Compound
import { createPublicClient, http, getContract, parseAbi } from "viem";
const BAULT_ABI = parseAbi([
"function bounty() external view returns (uint256)",
"function earned() external view returns (uint256)",
"function previewClaimBgtWrapper(address wrapper) external view returns (uint256)"
]);
async function checkBault(baultAddress: string) {
const bault = getContract({
address: baultAddress,
abi: BAULT_ABI,
client: publicClient
});
// Get current bounty requirement
const bounty = await bault.read.bounty();
// Get earned BGT available to claim
const earnedBGT = await bault.read.earned();
// Preview how much wrapper we'd get (using iBGT as example)
const wrapperAmount = await bault.read.previewClaimBgtWrapper([wrapperOfChoice]); // ibgt for example
console.log(`Bounty required: ${bounty}`);
console.log(`BGT earned: ${earnedBGT}`);
console.log(`Wrapper amount: ${wrapperAmount}`);
return { bounty, earnedBGT, wrapperAmount };
}
Step 2: Check Profitability
async function isProfitable(baultAddress: string) {
const { bounty, wrapperAmount } = await checkBault(baultAddress);
// Get staking token address
const stakingToken = await client.readContract({
address: baultAddress,
abi: BAULT_ABI,
functionName: 'stakingToken',
});
// Get swap quote: wrapper -> staking token (enso router preffered)
const quote = await getSwapQuote(
iBGT_ADDRESS,
stakingToken,
wrapperAmount.toString()
);
// Check if swap output covers the bounty
const isReady = BigInt(quote.amountOut) >= bounty;
console.log(`Swap will give us: ${quote.amountOut}`);
console.log(`Bounty required: ${bounty}`);
console.log(`Ready to compound: ${isReady}`);
return { isReady, quote };
}
// Helper function for getting swap quotes in desired format
async function getSwapQuote(fromToken: string, toToken: string, amount: string) {
// This is where you'd integrate with:
// - Enso Router (recommended)
// - Your custom routing functions.
// - Any other swap router
// Your goal is to swap/exchange the claimed bgt wrapper into the underlying staking token (Kodiak island tokens)
const quote = await fetch('/api/swap-quote', {
method: 'POST',
body: JSON.stringify({
fromToken, // iBGT address
toToken, // Staking token address
amount, // Wrapper amount to swap
slippage: 500 // 5%
})
});
return await quote.json(); // { amountOut, calldata, to }
}
Step 3: Execute Compound Transaction
const BOUNTY_HELPER_ABI = parseAbi([
`function claimBgtWrapper(
address bault,
address bgtWrapper,
address swapTarget,
bytes calldata swapData,
uint256 wrapperAmount,
address bountyReceiver
) external`
]);
async function compoundBault(baultAddress: string) {
// Get all the data we need
const { wrapperAmount } = await checkBault(baultAddress);
const { quote, isProfitable } = await isProfitable(baultAddress);
const BOUNTY_HELPER_ADDRESS = "0x..."; // BountyHelper contract
const PROFIT_RECEIVER = "0x..."; // Any address that should get the excess bgt claimed/staking token left after repaying bounty
// Execute the compound transaction
const txHash = await walletClient.writeContract({
address: BOUNTY_HELPER_ADDRESS,
abi: BOUNTY_HELPER_ABI,
functionName: 'claimBgtWrapper',
args: [
baultAddress, // Which bault to compound
iBGT_ADDRESS, // BGT wrapper to use
quote.to, // Swap router address
quote.calldata, // Swap transaction data
wrapperAmount, // Amount of wrapper to claim
PROFIT_RECEIVER // Where to send the bounty profit
]
});
console.log(`Compound transaction sent: ${txHash}`);
return txHash;
}
Key Points
What You Need
A wallet with some BERA for gas
Access to a swap router (Enso recommended).
Get your enso api key here (https://shortcuts.enso.finance/developers)
Look at how to use the api here (https://docs.enso.build/api-reference/defi-shortcuts/optimal-route-between-two-tokens)
RPC endpoint for Berachain (https://rpc.kodiak.finance)
How You Profit
You earn the excess bounty (mostly in staking tokens) for each successful compound
No upfront capital required - BountyHelper funds the bounty