Earn integration
Tranche ids
| Product | variant | epochs to pass | id minted |
|---|---|---|---|
| avBTCm | 1 | 4 | 65540 (0x010004) |
| avMEZOm | 2 | 208 | 131280 (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
depositErc20ordepositVeNft→ ERC-1155 toto.- Optional wrap: ERC-1155
safeTransferFromto the ID20. - Optional
Id20Gauge.activate()(permanent). - Harvest:
Ledger.claimRebases(trancheId, tokenIds)then sinkclaimRewardsand/orAuroveId20.claimRewards(), thenId20Gauge.claim(receiver). - Exit:
unwrap(amount, to)thenredeem(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
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
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
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",
);| Name | Address | Role | Type | Verification |
|---|---|---|---|---|
| Ledger | 0x0AF3601f0E15b8E33fEc660fBE515DDb6C54dD3c | ERC-1155 accounting surface for deposits, redemptions, and rebase claims. | Proxy | |
| Vault | 0x708E1B58bCDb05eF3a2CE9FbF9D1987F547238c9 | Custodies veNFTs, deploys managers and sinks, and releases inventory on redeem. | Proxy | |
| avBTCm manager | 0x3b3223C036D939Ece4aDc2a5Dd489423E4EF49FF | Owns the managed veBTC position for the avBTCm tranche. | Beacon proxy | |
| avMEZOm manager | 0x8210669B03313AAD9290D779f5cC4770992e1dd4 | Owns the managed veMEZO position for the avMEZOm tranche. | Beacon proxy | |
| avBTCm RewardSink | 0x249Cf321be802e2c7FFC3050F374060Fb2b5C5E0 | Holds and distributes avBTCm ERC-1155 reward units. | Beacon proxy | |
| avMEZOm RewardSink | 0xe379e4805EEEACe864FB6b35b43589B60d7b2577 | Holds and distributes avMEZOm ERC-1155 reward units. | Beacon proxy | |
| Id20Factory | 0xf7B7e122Ce45b48b53A8452188461bbDd115b935 | Deploys one immutable AuroveId20 wrapper and Id20Gauge per tranche. | Factory | |
| avBTCm | 0xf333171788dE7005695b2E8FB9cAE97Ba9c4dD7a | ERC-20 ID20 wrapper for the managed BTC tranche. 18 decimals. | Token | |
| avMEZOm | 0xb894b11A78B762c82Cb095148F5BC11DC93C3560 | ERC-20 ID20 wrapper for the managed MEZO tranche. 18 decimals. | Token | |
| avBTCm Id20Gauge | 0xA01D63da69A946747a0065bDaEa8c5f6ac4E6fdf | Instant ID20 reward gauge for avBTCm holders who activate. | Gauge | |
| avMEZOm Id20Gauge | 0xB50A13B20bBCC48D28fb728961B79334b8527aBD | Instant ID20 reward gauge for avMEZOm holders who activate. | Gauge |
Matching UI: Create a liquid position.
