Doji docs
Built on Mezo

How Doji uses Mezo

Every Mezo contract Doji calls, the exact functions, why each matters, and the testnet and mainnet addresses.

Doji is built on Mezo's own pieces. The collateral is veBTC, the loan is MUSD, the price is MUSD's own price feed, and the borrower's votes and fees keep flowing through Mezo's voters and fee distributor. Take Mezo away and nothing is left.

Every Mezo contract Doji calls

Testnet addresses are the ones in Doji's deployment record. Mainnet addresses are Mezo's live mainnet contracts, checked on Mezo's explorer and chain, and the fork tests run Doji against them.

Mezo contractFunctions Doji callsWhyTestnet (31611)Mainnet (31612)
veBTC, Mezo's vote-escrow Bitcoin NFTtransferFrom, createLockFor, locked, ownerOf, escrowType, grantManager, voted, increaseUnlockTime, unlockPermanent, withdrawThe collateral itself. Doji pulls or mints the position, reads the lock through one decoder, accepts only ordinary escrow with no grant manager, extends the lock for its borrower, and withdraws an unsold lock at settle.0xB63fcCd03521Cf21907627bd7fA465C1294792310x3D4b1b884A7a1E59fE8589a3296EC8f8cBB6f279
PoolsVoter (on testnet, the older voter that testnet veBTC names)vote, reset, claimFees, claimBribes, gaugeToFees, gaugeToBribe, isWhitelistedToken, usedWeightsThe borrower keeps voting and claiming pool fees and incentives through Doji. Reward contracts and tokens are looked up from PoolsVoter itself. Settle clears the vote first.0x72F8dd7F44fFa19E45955aa20A5486E8EB2557380x48233cCC97B87Ba93bCA212cbEe48e3210211f03
ValidatorsVoterusedWeights, resetMainnet veBTC also counts votes here, and a lock with a standing vote cannot be withdrawn, so prepareSettle resets it when it holds one.none: testnet veBTC has no secondary voters0xe99a9ad5Ed26BD30e4DB25397f378817e9b9515a
veBTC fee distributorclaim (the site also reads claimable)The position's share of chain fees keeps flowing to its borrower through claimRebase.0x10B0E7b3411F4A38ca2F6BB697aA28D6079247290xb58477e074265BdC7F7ca6100eD0f7De264F74A2
MUSDtransferFrom, transfer, balanceOf, approveThe loan currency. Every pull is exact and measured. LoanManager gives CreditMarkets a standing allowance at deployment so repayments can be booked into their date.0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac5030xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186
MUSD PriceFeedfetchPriceThe one BTC price for limits, auctions and settle. It refuses a Skip answer older than 60 seconds, and Doji then refuses to borrow, roll, start an auction, sell or settle.0x86bCF0841622a5dAC14A313a15f96A95421b93660xc5aC5A8892230E0A3e1c473881A2de7353fFcA88
Skip BTC/USD oraclenone directly: PriceFeed reads itThe source of the price, 18 decimals.0x7b7c0000000000000000000000000000000000150x7b7c000000000000000000000000000000000015
BTC, Mezo's ERC-20 view of native BTCtransferFrom, approve, balanceOf, transferveBTC locks and pays in it. Doji pulls exactly the BTC to lock, approves veBTC for exactly that amount and resets it to zero, measures the BTC a withdrawal brings, and pays BTC to lenders and claimants.0x7b7C0000000000000000000000000000000000000x7b7C000000000000000000000000000000000000

Doji does not call BoostVoter. A mainnet fork test (test C in PassThroughFork.t.sol) checks that a BoostVoter vote leaves veBTC's voted flag alone, so it can never block a settle.

Mezo rules Doji is built around

  • Weekly epochs turn on Thursday 00:00 UTC, and veBTC lock ends fall on the same boundaries. That is why every Doji loan is due on a Thursday.
  • A veBTC lock lasts at most 28 days, so no Doji loan runs longer than 4 weeks, permanent lock or not.
  • Votes persist from epoch to epoch. Each position gets one vote or reset per epoch, none in an epoch's first hour, and a lock with a standing vote cannot be withdrawn. Doji blocks votes in a normal lock's last week, so the reset settle needs is always possible.
  • locked() returns three words on testnet's older veBTC and four on mainnet (with a boost). One reader decodes it for the chain it was deployed on and refuses anything else.

What Doji never touches

LoanManager acts on positions only through the calls in the table. It gives no veBTC approval or approval-for-all, has no generic call or multicall, never merges, splits or makes a lock permanent, and never swaps on a DEX. It accepts no meta-transactions and has no forwarder: every call acts for the address that sent it.

On 5 October 2026 an attacker moved 37 veBTC positions on Mezo mainnet through a flaw in how a trusted forwarder (Mezo's meta-transaction path) passed on the sender. Mezo has since turned meta-transactions on veBTC off, and live veBTC's forwarder() returns the zero address (Mezo's incident report). A contract that holds many positions concentrates exactly that kind of risk, which is why custody comes first in Doji's threat model. One non-goal remains and is stated: Mezo's PoolsVoter still trusts an ERC-2771 forwarder. A flaw there could act as LoanManager on PoolsVoter (vote, reset, claim). Rewards would still land with LoanManager, and the worst outcome is a delayed settle.

Testnet and mainnet

Doji is deployed on Mezo testnet only, and its deploy script refuses mainnet. Testnet runs an older veBTC: three-word locked(), no veMEZO boost and no secondary voters. Mainnet behaviour is proven by fork tests that run Doji against real mainnet positions, the real voters, MUSD and the fee distributor. See Run the proof yourself.