Skip to content

boar-network/boar-finance-integration-docs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

Boar Finance Integration Guide

Boar Finance lets users lock BTC into veBTC positions on Mezo and delegate voting power to managed position. Boar Finance votes and compounds rewards on behalf of all delegators, earning yield each epoch (7 days).

By integrating Boar Finance, you give your users access to BTC yield on Mezo. In return, locks created through your integration are attributed to you via on-chain referrer tracking, enabling revenue-share based on the TVL you bring.

Note

Reference implementation: See example/ for a working React app that implements the full flow below.

Quick Start

The integration requires two user interactions:

  1. Sign permit + Lock - User signs a gasless permit, then locks BTC through LockGateway with your referrer address
  2. Delegate - Delegate the resulting veBTC NFT to Boar's managed position
import { parseUnits, parseSignature, decodeEventLog, toEventSelector } from "viem"

const YOUR_REFERRER_ADDRESS = "0xYourAddress" // Replace with your address for revenue attribution
const LOCK_GATEWAY = "0xb4C0eA5E674Cd32D93EbE94F9d2a31CeB0490132" // mainnet
const POOLS_VOTER = "0x48233cCC97B87Ba93bCA212cbEe48e3210211f03"  // mainnet
const BTC_TOKEN = "0x7b7C000000000000000000000000000000000000"
const BOAR_TOKEN_ID = 1226n // mainnet

const amount = parseUnits("0.1", 18) // 0.1 BTC
const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600) // 1 hour

// Step 1: Sign EIP-2612 permit (off-chain, no gas)
const [nonce, name] = await Promise.all([
  publicClient.readContract({
    address: BTC_TOKEN,
    abi: btcAbi,
    functionName: "nonce",
    args: [userAddress],
  }),
  publicClient.readContract({
    address: BTC_TOKEN,
    abi: btcAbi,
    functionName: "name",
  }),
])

const signature = await walletClient.signTypedData({
  domain: {
    name,
    version: "1",
    chainId: 31612,
    verifyingContract: BTC_TOKEN,
  },
  types: {
    Permit: [
      { name: "owner", type: "address" },
      { name: "spender", type: "address" },
      { name: "value", type: "uint256" },
      { name: "nonce", type: "uint256" },
      { name: "deadline", type: "uint256" },
    ],
  },
  primaryType: "Permit",
  message: {
    owner: userAddress,
    spender: LOCK_GATEWAY,
    value: amount,
    nonce,
    deadline,
  },
})

const { v, r, s } = parseSignature(signature)

// Step 2: Lock with permit + referrer (single transaction)
const txHash = await walletClient.writeContract({
  address: LOCK_GATEWAY,
  abi: lockGatewayAbi,
  functionName: "lock",
  args: [amount, deadline, Number(v), r, s, YOUR_REFERRER_ADDRESS],
})

// Read tokenId from the Locked event in the receipt
const LOCKED_TOPIC = toEventSelector("Locked(address,uint256,uint256,address)")
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash })
let tokenId: bigint | undefined
for (const log of receipt.logs) {
  if (log.address.toLowerCase() !== LOCK_GATEWAY.toLowerCase()) continue
  if (log.topics[0] !== LOCKED_TOPIC) continue
  const decoded = decodeEventLog({ abi: lockGatewayAbi, data: log.data, topics: log.topics })
  if (decoded.eventName === "Locked" && "tokenId" in decoded.args) {
    tokenId = decoded.args.tokenId as bigint
    break
  }
}

// Step 3: Delegate to Boar
await walletClient.writeContract({
  address: POOLS_VOTER,
  abi: poolsVoterAbi,
  functionName: "depositManaged",
  args: [tokenId, BOAR_TOKEN_ID],
})

Important

Delegation will revert during the distribution window (first hour of each epoch, Thu 00:00-01:00 UTC). See Constraints for details.

Note

Mezo is an EVM-compatible L2 that uses BTC as its native gas token. Users need a small amount of native BTC for gas in addition to the BTC ERC-20 token used for locking.

Referrer Tracking

Pass your address as the referrer parameter when calling lock. Every lock emits a Locked event that permanently associates the referrer with the minted tokenId:

event Locked(
    address indexed user,
    uint256 indexed tokenId,
    uint256 amount,
    address referrer
);

Boar uses these events to track which locks were created through your integration and calculates revenue-share per epoch based on the delegated TVL attributed to you.

Locking Methods

LockGateway provides two ways to lock BTC. Both support optional referrer tracking.

lock (approve flow)

The user pre-approves BTC spending, then locks in a second transaction. Works with all wallet types. Referrer is required - without referrer tracking there is no reason to use the gateway (users can lock directly via veBTC.createLock).

LockGateway.lock(amount, referrer) → tokenId

lock (permit flow)

The user signs an EIP-2612 permit off-chain, then locks in a single transaction (no separate approve needed). Only works with wallets that support eth_signTypedData.

// With referrer
LockGateway.lock(amount, permitDeadline, v, r, s, referrer) → tokenId

// Without referrer
LockGateway.lock(amount, permitDeadline, v, r, s) → tokenId

Parameters

Parameter Type Description
amount uint256 BTC to lock (18 decimals)
referrer address Your address for rev-share attribution
permitDeadline uint256 Unix timestamp, permit expiry (permit flow only)
v, r, s uint8, bytes32, bytes32 EIP-2612 permit signature (permit flow only)

Lock duration is 28 days (4 epochs) in the contract and remains as such after undelegation.

Both methods return tokenId (uint256) - the ID of the newly minted veBTC NFT, needed for the delegation step.

Delegation

After locking, delegate the veBTC NFT to Boar's managed position:

PoolsVoter.depositManaged(tokenId, boarTokenId)

After delegation, Boar votes and compounds rewards on behalf of the user. The lock's voting power is consolidated under Boar's managed position.

Constraints

Important

  • Only NORMAL type locks can be delegated (freshly created locks are always NORMAL)
  • Cannot delegate during the distribution window (first hour of each epoch)
  • Epochs flip every 7 days, every Thursday at 00:00:00 UTC. Check the current epoch boundary via PoolsVoter.epochNext(block.timestamp) or the Boar Finance dashboard.
  • If the lock has active votes from a previous delegation, call PoolsVoter.reset(tokenId) first

Reading Positions

Get user's locks

uint256 count = VeBTC.balanceOf(userAddress);
for (uint256 i = 0; i < count; i++) {
    uint256 tokenId = VeBTC.ownerToNFTokenIdList(userAddress, i);

    // Lock details: amount (int128), end (uint256), isPermanent (bool), boost (uint256)
    VeBTC.locked(tokenId);

    // Voting power
    VeBTC.votingPowerOfNFT(tokenId);

    // Lock type:
    //   0 = NORMAL  - freshly created, not yet delegated
    //   1 = LOCKED  - delegated to a managed position (via depositManaged)
    //   2 = MANAGED - Boar's own managed position
    VeBTC.escrowType(tokenId);
}

Check delegation status

// Returns the managed token ID this lock is delegated to (0 if not delegated)
PoolsVoter.idToManaged(tokenId);

Yield

Yield auto-compounds each epoch (7 days). Delegators do not need to claim or take any action - Boar handles voting and compounding automatically. The compounded yield increases the voting power and underlying BTC amount of the managed position.

To check current APY, visit the Boar Finance dashboard. APY varies per epoch based on the total BTC delegated and the rewards distributed.

Undelegation and Withdrawal

Undelegate

PoolsVoter.withdrawManaged(tokenId);

After undelegation, the lock's end time extends to 28 days from the current epoch.

Withdraw BTC

VeBTC.withdraw(tokenId);

Only possible after the lock's end timestamp has passed.

Contract Addresses

Mainnet (Chain ID: 31612)

Contract Address
BTC (ERC-20) 0x7b7C000000000000000000000000000000000000
LockGateway 0xb4C0eA5E674Cd32D93EbE94F9d2a31CeB0490132
veBTC (VotingEscrow) 0x3D4b1b884A7a1E59fE8589a3296EC8f8cBB6f279
Boar Managed Token 1226 (pass as _mTokenId to depositManaged)

Testnet (Chain ID: 31611)

Contract Address
BTC (ERC-20) 0x7b7C000000000000000000000000000000000000
LockGateway 0x8B2de1591843D1B167035c654CC476A28548470C
veBTC (VotingEscrow) 0x38E35d92E6Bfc6787272A62345856B13eA12130a
Boar Managed Token 503 (pass as _mTokenId to depositManaged)

Network

Mainnet Testnet
Chain ID 31612 31611
RPC See chainlist https://rpc.test.mezo.org
Explorer https://explorer.mezo.org https://explorer.test.mezo.org

Important

For production use, contact Boar RPC team for a dedicated endpoint or pick a public RPC from chainlist.

Epoch Timeline

  • Epoch duration: 7 days (604,800 seconds). Epochs flip every Thursday at 00:00:00 UTC.
  • Distribution window: First hour of each epoch (Thu 00:00-01:00 UTC). No delegation or withdrawal during this time.
  • Lock duration: 28 days (4 epochs)

About

Boar Finance Vault integration documentation for partners.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors