Distribution Vault
Also called TTGVault
or Vault
.
Overview
The Distribution Vault is a core component of M0's economic infrastructure designed to collect, account for, and distribute various forms of protocol revenue and yield to Zero token holders. It serves as the primary mechanism for value capture within the protocol's Two Token Governance (TTG) system, turning protocol operations into direct economic benefits for governance participants.
Purpose and Role in the Ecosystem
The Distribution Vault functions as:
- Revenue Collector: Accumulates various forms of protocol revenue from multiple sources
- Yield Distributor: Enables proportional distribution of accumulated tokens to Zero token holders
- Value Capture Mechanism: Creates a direct incentive for governance participation
- Economic Bridge: Links protocol activity with governance token value
Architecture Overview
The Distribution Vault is referenced throughout the system as TTGVault
or simply vault
. Its address is established during deployment and made accessible to other core contracts via the Registrar
or specific deployer contracts.

Revenue Sources
The Distribution Vault accumulates tokens from four primary sources:
1. Excess $M token Yield (from MinterGateway
)
This represents a continuous source of $M token revenue coming from the interest rate spread between minters and earners.
Mechanism:- The
MinterGateway.updateIndex()
function calculatesexcessOwedM()
- the difference between total owed M (based on minter interest rate) and actual total M supply (growing at the earner interest rate) - When positive, this excess amount is minted directly to the Distribution Vault
- Interest Rate Spread: The inherent difference between the higher interest rate charged to minters vs. the lower rate paid to earners (capped at 98% of the "safe rate")
- Rounding Differences: Accumulated from principal-to-present value conversions within the continuous indexing math
- Penalties: Charges imposed on minters for missed collateral updates or undercollateralization
// In MinterGateway.sol
function updateIndex() public override(IContinuousIndexing, ContinuousIndexing) returns (uint128 index_) {
uint240 excessOwedM_ = excessOwedM();
if (excessOwedM_ > 0) IMToken(mToken).mint(ttgVault, excessOwedM_); // Mint M to TTG Vault
index_ = super.updateIndex(); // Update minter index and rate
IMToken(mToken).updateIndex(); // Update earning index and rate
}
2. Power token Auction Proceeds (from Power token)
The Power token contract auctions off newly inflated tokens in non-voting epochs, with proceeds directed to the vault.
Mechanism:- Power token employs a Dutch auction mechanism where price decreases over time
- When users purchase Power token via the
buy()
function, the calculated cost incashToken
is sent to the Distribution Vault
// In Power token.sol
function buy(
uint256 minAmount_,
uint256 maxAmount_,
address destination_,
uint16 expiryEpoch_
) external returns (uint240 amount_, uint256 cost_) {
// ... calculations for amount_ and cost_ ...
emit Buy(msg.sender, amount_, cost_ = getCost(amount_));
_mint(destination_, amount_);
if (!ERC20Helper.transferFrom(cashToken(), msg.sender, vault, cost_)) revert TransferFromFailed();
}
3. Forfeited Standard Governor Proposal Fees (from StandardGovernor
)
Fees submitted with proposals in the StandardGovernor
flow to the Distribution Vault if the proposal fails.
- When creating a proposal via ``StandardGovernor
.propose()
, proposers pay a fee in the system'scashToken
- If the proposal succeeds, the fee is returned to the proposer
- If the proposal is defeated or expires, the fee is sent to the Distribution Vault via
sendProposalFeeToVault()
// In `StandardGovernor`.sol
function sendProposalFeeToVault(uint256 proposalId_) external {
ProposalState state_ = state(proposalId_);
if (state_ != ProposalState.Expired && state_ != ProposalState.Defeated) revert FeeNotDestinedForVault(state_);
uint256 proposalFee_ = _proposalFees[proposalId_].fee;
if (proposalFee_ == 0) revert NoFeeToSend();
address cashToken_ = _proposalFees[proposalId_].cashToken;
delete _proposalFees[proposalId_];
emit ProposalFeeSentToVault(proposalId_, cashToken_, proposalFee_);
_transfer(cashToken_, vault, proposalFee_);
}
4. Direct/Arbitrary Transfers
The Distribution Vault can receive tokens via direct transfers from any account or contract. These tokens need to be explicitly "registered" for distribution.
Mechanism:- Tokens can be transferred directly to the vault contract address at any time using a standard ERC20
transfer
ortransferFrom
. - To make these externally transferred tokens available for claiming, the external
distribute(token)
function must be called for the specifictoken_
address. - The
distribute(token)
function calculates the increase in the vault's balance oftoken_
since the last time distribute was called for that token (using the internal_lastTokenBalances
tracking). It then registers this newly available amount (amount_
) within thecurrentEpoch_
(the epoch whendistribute()
is called). - Crucially, Zero token holders who held tokens during this
currentEpoch_
become eligible to claim a share of this distributedamount_
. The claimable share for each eligible holder is calculated pro-rata based on their fractional Zero token ownership as snapshotted at the end of that specificcurrentEpoch_
.
// In DistributionVault.sol
function distribute(address token_) external returns (uint256 amount_) {
uint256 currentEpoch_ = clock();
amount_ = getDistributable(token_);
emit Distribution(token_, currentEpoch_, amount_);
unchecked {
distributionOfAt[token_][currentEpoch_] += amount_; // Add to the distribution for the current epoch
_lastTokenBalances[token_] += amount_; // Track this contract's latest balance
}
}
function getDistributable(address token_) public view returns (uint256) {
return IERC20(token_).balanceOf(address(this)) - _lastTokenBalances[token_];
}
Distribution Mechanism
The Distribution Vault implements a sophisticated epoch-based, pro-rata distribution system that ensures fair allocation of accumulated tokens to Zero token holders.
Core Mechanics
- Epoch-Based Accounting: Each token distribution is recorded in the current epoch (a time period, typically 15 days)
- Historical Balances: Claims are calculated based on Zero token holders' balances during past epochs
- Pro-Rata Distribution: Tokens are distributed proportionally to Zero token holdings
- Claimable Design: Zero token holders must claim their share of distributed tokens
Distribution Process
- Accumulation: Tokens flow into the vault through various mechanisms
- Registration: The
distribute(token)
function is called, recording the new token amount for the current epoch - Claiming: Zero token holders call
claim()
orclaimBySig()
to receive their share for specific epochs - Calculation: The claimable amount is computed based on the holder's proportional ownership during each claimed epoch
Key Functions
// Allows claiming tokens for a specific address
function claim(
address token_,
uint256 startEpoch_,
uint256 endEpoch_,
address destination_
) external returns (uint256 claimed_)
// Allows claiming with a signature (helpful for gas-less transactions)
function claimBySig(
address account_,
address token_,
uint256 startEpoch_,
uint256 endEpoch_,
address destination_,
uint256 deadline_,
bytes memory signature_
) external returns (uint256 claimed_)
// Calculates the claimable amount for a given address, token, and epoch range
function getClaimable(
address token_,
address account_,
uint256 startEpoch_,
uint256 endEpoch_
) public view returns (uint256 claimable_)
Technical Implementation Details
Contract Structure
The Distribution Vault inherits from StatefulERC712, which provides EIP-712 signature verification functionality:
contract DistributionVault is IDistributionVault, StatefulERC712 {
// ... implementation ...
}
Key State Variables
// The scale to apply when accumulating an account's claimable token to minimize precision loss
uint256 internal constant _GRANULARITY = 1e9;
// EIP-712 typehash for claim function
bytes32 public constant CLAIM_TYPEHASH = 0x4b4633c3c305de33d5d9cf70f2712f26961648cd68d020c2556a9e43be58051d;
// Address of the Zero Token contract
address public immutable zeroToken;
// Mapping of last recorded balance per token
mapping(address token => uint256 balance) internal _lastTokenBalances;
// Mapping of distributions per token, epoch, and amount
mapping(address token => mapping(uint256 epoch => uint256 amount)) public distributionOfAt;
// Mapping of claimed status per token, epoch, and account
mapping(address token => mapping(uint256 epoch => mapping(address account => bool claimed))) public hasClaimed;
Signature-Based Claims
The Distribution Vault supports signature-based claims, allowing users to authorize others to claim on their behalf:
function claimBySig(
address account_,
address token_,
uint256 startEpoch_,
uint256 endEpoch_,
address destination_,
uint256 deadline_,
uint8 v_,
bytes32 r_,
bytes32 s_
) external returns (uint256) {
// ... signature verification logic ...
// ... deadline verification ...
return _claim(account_, token_, startEpoch_, endEpoch_, destination_);
}
Economic Implications
The Distribution Vault creates several important economic effects:
- Zero token Value Accrual: By directing protocol revenue to Zero token holders, it increases the token's economic value
- Governance Incentive Alignment: Creates a direct financial incentive for governance participation
- Sustainable Protocol Economics: Ensures that excess yield and protocol fees flow back to governance participants
- Diversified Revenue Streams: Collects different token types from multiple sources, creating a robust revenue model
Integration with the Wrapped $M token (Extended)
The Distribution Vault also interacts with the Wrapped $M (wM) system:
- Excess Yield Destination: The wM contract can send excess yield to the Distribution Vault via its
claimExcess()
function - Economic Loop Completion: This creates a complete economic loop where even wrapped token operations can generate value for governance participants
Conclusion
The Distribution Vault stands as a critical infrastructure component in the M0 protocol, serving as the central hub for value capture and redistribution. Through its sophisticated pro-rata distribution mechanism, it ensures that protocol operations consistently generate value for governance participants, creating strong economic incentives for system participation and alignment.
By collecting revenue from multiple sources and making it claimable by Zero token holders, the vault creates a direct financial link between protocol usage and governance value, strengthening the economic sustainability of the entire ecosystem.
One can check straight on the dashboard the number of M accumulated by the vault and not claimed so far.