Developers

Earn integration

Tranche ids

Productvariantepochs to passid minted
avBTCm1465540 (0x010004)
avMEZOm2208131280 (0x0200d0)

Always pass the managed sentinel as epochs. The ABI still includes the argument; the implementation ignores it and mints the managed id. Collection metadata: Liquid locked veNFTs - Aurove / avNFTs. Read the wrapper tranche with AuroveId20.id() (not trancheId()). The linked Id20Gauge is rewardSink() on the wrapper and id20() on the gauge.

Required approvals

  • ERC-20 deposit: approve BTC or MEZO for the Ledger, amount in 18-decimal wei.
  • veNFT deposit: approve the specific token id, or setApprovalForAll, for the Ledger.
  • Wrap: setApprovalForAll(id20, true) on the Ledger if the wrapper is not already an operator.

Mutative sequence

  1. depositErc20 or depositVeNft → ERC-1155 to to.
  2. Optional wrap: ERC-1155 safeTransferFrom to the ID20.
  3. Optional Id20Gauge.activate() (permanent).
  4. Harvest: Ledger.claimRebases(trancheId, tokenIds) then sink claimRewards and/or AuroveId20.claimRewards(), then Id20Gauge.claim(receiver).
  5. Exit: unwrap(amount, to) then redeem(trancheId, amount, receiver, tokenIds).

Reward fee reads

A successful distributor claim may fund the current LMR epoch without increasing any child's earned() yet. Do not equate that transfer with RewardSink funding or fee collection, or infer that zero claimable growth means an exit forfeits nothing. See LMR settlement for the separate allocation boundary and early-exit example.

The protocol fee applies when a tranche RewardSink syncs newly detected reward funding, including inventory growth minted by Ledger.claimRebases. It is transferred from the sink to the collector as ERC-1155 units of the same tranche before the net reward amount is notified. Claim transactions receive already-netted rewards.

Do not hard-code or infer the live fee. Read Ledger.feeConfig() for the active fee and Ledger.nextFeeConfig() for any pending update, either on-chain or from the Ledger Contract tab on the Mezo explorer. The owner-only proposeFeeConfig creates a pending config for the next weekly epoch when called outside the final 48 hours of the current epoch; executeFeeConfig is permissionless after that effective epoch and is what actually activates the pending values.

Read-only examples

TypeScriptread-tranche.ts
import { createPublicClient, http } from "viem";
import { getId20FactoryAbi, getLedgerAbi } from "@/contracts/earn";
import { mezoMainnetChain } from "@/lib/config/chains";
import { MEZO_CHAIN_ID, TRANCHE_PRODUCTS } from "@/lib/docs/contracts-reference";
import { docsExampleAddresses } from "@/lib/docs/examples";

const client = createPublicClient({
  chain: mezoMainnetChain,
  transport: http(mezoMainnetChain.rpcUrls.default.http[0]),
});
const { ledger, id20Factory } = docsExampleAddresses();
const avBtcTrancheId = BigInt(TRANCHE_PRODUCTS[0].trancheId);

const supply = await client.readContract({
  address: ledger,
  abi: getLedgerAbi(MEZO_CHAIN_ID)!,
  functionName: "totalSupply",
  args: [avBtcTrancheId],
});

const wrapper = await client.readContract({
  address: id20Factory,
  abi: getId20FactoryAbi(MEZO_CHAIN_ID)!,
  functionName: "getId20",
  args: [avBtcTrancheId],
});

The same helpers live in dapp/lib/docs/examples.ts and are type-checked with the dApp.

Constructing a deposit

TypeScriptdeposit-erc20.ts
import { getAddress, type Address } from "viem";
import { depositErc20CalldataArgs } from "@/lib/docs/examples";

// Ledger.depositErc20(uint8 variant, uint256 epochs, uint256 amount, address to)
// variant 1 = BTC, 2 = MEZO. epochs must be the managed sentinel (4 or 208);
// the Ledger ignores the value and mints the managed tranche.
const args = depositErc20CalldataArgs({
  variant: 1,
  amount: 10n ** 16n, // 0.01 BTC, 18 decimals
  receiver: getAddress("0x0000000000000000000000000000000000000001") as Address,
});
// Approve BTC for the Ledger before sending depositErc20(...args).

Wrapping

TypeScriptwrap-data.ts
import { wrapTrancheTransferData } from "@/lib/docs/examples";

// No wrap() method exists. Transfer ERC-1155 tranche units to the ID20 address.
// data = 0x mints to the ERC-1155 sender.
// data = abi.encode(recipient) mints to that recipient.
const dataToSelf = wrapTrancheTransferData();
const dataToRecipient = wrapTrancheTransferData(
  "0x0000000000000000000000000000000000000001",
);
NameAddressRoleTypeVerification
Ledger0x0AF3601f0E15b8E33fEc660fBE515DDb6C54dD3cERC-1155 accounting surface for deposits, redemptions, and rebase claims.Proxy
Vault0x708E1B58bCDb05eF3a2CE9FbF9D1987F547238c9Custodies veNFTs, deploys managers and sinks, and releases inventory on redeem.Proxy
avBTCm manager0x3b3223C036D939Ece4aDc2a5Dd489423E4EF49FFOwns the managed veBTC position for the avBTCm tranche.Beacon proxy
avMEZOm manager0x8210669B03313AAD9290D779f5cC4770992e1dd4Owns the managed veMEZO position for the avMEZOm tranche.Beacon proxy
avBTCm RewardSink0x249Cf321be802e2c7FFC3050F374060Fb2b5C5E0Holds and distributes avBTCm ERC-1155 reward units.Beacon proxy
avMEZOm RewardSink0xe379e4805EEEACe864FB6b35b43589B60d7b2577Holds and distributes avMEZOm ERC-1155 reward units.Beacon proxy
Id20Factory0xf7B7e122Ce45b48b53A8452188461bbDd115b935Deploys one immutable AuroveId20 wrapper and Id20Gauge per tranche.Factory
avBTCm0xf333171788dE7005695b2E8FB9cAE97Ba9c4dD7aERC-20 ID20 wrapper for the managed BTC tranche. 18 decimals.Token
avMEZOm0xb894b11A78B762c82Cb095148F5BC11DC93C3560ERC-20 ID20 wrapper for the managed MEZO tranche. 18 decimals.Token
avBTCm Id20Gauge0xA01D63da69A946747a0065bDaEa8c5f6ac4E6fdfInstant ID20 reward gauge for avBTCm holders who activate.Gauge
avMEZOm Id20Gauge0xB50A13B20bBCC48D28fb728961B79334b8527aBDInstant ID20 reward gauge for avMEZOm holders who activate.Gauge

Matching UI: Create a liquid position.

developersearndepositredeemwrap