SplitterTreasury_v1 contract that divides each payment between elevation and a list of recipients in the same transaction.
The buy fee, sell fee, origination fee and LTV are parameters of a market. Their values set the cost of trading and borrowing and the amount of fee the market collects. The splitter’s settings decide how much of that fee goes to recipients and how much goes to elevation, which raises the reference price.
Fees a market charges
The code calls the origination fee the borrowing fee (
setBorrowingFeeRate, getBorrowingFeeRate). This page uses “origination fee” for the same parameter.
One further payment reaches the market fee treasury. When a sell takes supply to 0 and the reserve manager records no outstanding draws, the market sends any collateral left on the curve contract to the fee treasury (Markets and curves).
The fee treasury address
The factory creates the market fee treasury when it creates the market (ReferenceCurveFactory_v1). It passes the same address to the curve and to every module it creates with the market, including the credit facility and the staking manager. Each contract stores the address at initialization (__Module_init). No contract has a function that changes it.
Every fee follows the same path. The contract that charges the fee approves the fee treasury for the amount and calls the treasury’s fetchFunds (_sendFeesToTreasury). The treasury pulls the amount and divides it in the same call.
The early-access module is attached to the market later, with its own SplitterTreasury_v1 (attachPresaleWithTreasury). Its fee goes to that treasury, not to the market fee treasury. The launch route reverts if the two addresses are the same.
Origination fee
The credit facility charges the origination fee on every loan it opens:borrow, each round of buyAndBorrow, and the collateral released by rebalanceLoan. The fee is taken from the loan amount, and the borrower receives the rest.
where:
- is the loan amount, in collateral
- is the origination fee in basis points (
getBorrowingFeeRate)
The loan amount follows from the locked issuance tokens, the reference price and the LTV. Credit and looping explains that calculation.
The split
The splitter holds three settings:- an elevation percentage: a share of each payment, in basis points, that it sends first to the elevation fee address
- a list of recipients, each with a share count
- an optional elevation treasury share: a destination address (
getElevationTreasury) with its own share count, counted together with the recipient shares. In theshareslaunch mode the destination is the market’sElevationTreasury_v1
fetchFunds is called, the splitter pulls the payment, then works out its distributable amount: its whole balance of that token, less any elevation value already pending (see Elevation treasury share payments). It sends the elevation percentage of the distributable amount to the elevation fee address. It divides the rest by share count between the destination of the elevation treasury share and the recipients.
where:
- is the splitter’s balance of the token after it pulls the payment
- is the elevation value already pending for that token (
getPendingElevationReserved) - is the distributable amount
- is the elevation percentage in basis points (
getElevationFeePercentage) - is the amount sent to the elevation fee address (
getElevationFeeTreasury) - is the share count of the elevation treasury share (
getElevationShares), 0 when none is set - is recipient ‘s share count (
getRecipientsAndShares) - is the total share count (
getTotalShares) - is the amount offered to the destination of the elevation treasury share
- is the amount sent to recipient
fetchFunds call. A slice that rounds to 0 is not sent.
Example. A splitter has an elevation percentage of 500 bps (5%), two recipients A and B with 3 shares and 1 share, and an elevation treasury share of 1 share. Nothing is pending and the splitter holds nothing before a fee of 1,000.00 collateral arrives.
Of the 1,000.00 fee, 240.00 goes toward elevation (50.00 by the elevation percentage, 190.00 by share) and 760.00 goes to the two recipients.
Example with a remainder. The same splitter receives 1,001 of the collateral token’s smallest unit.
The 1 unit stays on the splitter and is included in the distributable amount of the next call.
Elevation treasury share payments
The two elevation routes move funds differently:- Elevation percentage: the splitter transfers to the elevation fee address directly.
- Elevation treasury share: the splitter records as pending for the share’s destination, approves the destination for its whole pending amount, and calls the destination’s
fetchFunds. The destination pulls the amount.
getPendingElevationPayment). A failed call to the destination does not revert the fee payment. The recipients are paid in the same call either way.
Pending value is excluded from the distributable amount of later calls. Each later fetchFunds call offers the current destination its pending amount plus the new slice. Any address can also call retryElevationPayment(token, treasury) to offer a destination its pending amount without a new payment. The call does nothing when nothing is pending.
From the elevation treasury to the curve
ElevationTreasury_v1 holds the collateral it receives. Its fetchFunds only accumulates and does not start an elevation. An elevation happens when an elevation keeper calls the treasury’s elevate. That call passes collateral to the curve’s elevate, which raises the reference price. How the reference price increases covers the conditions on that call and what it does to the curve.
Allocations made after the split
The splitter’s on-chain split consists of the elevation percentage, the recipients and the elevation treasury share. A recipient can send the collateral it receives to any address, including the market’s elevation treasury. The splitter does not record or restrict what a recipient does with that collateral. Any address can transfer collateral to the market’s elevation treasury, and the treasury treats that collateral the same as collateral from the splitter.Parameters
Each splitter’s first recipients, shares, elevation percentage and elevation fee address come from its initialization data. The launch route checks them against the launch configuration before it hands the admin role over.
DEFAULT_ADMIN_ROLE can call every setter on this page. Authority lists every role.
Scenarios
Elevation at launch
The launch route wires elevation on both splitters, the market fee treasury and the early-access fee treasury, in one of two modes set by the launch configuration (elevationMode).
Elevation treasury share payment outcomes
Edge cases
- Fee treasury fixed. No contract has a setter for its fee treasury address.
- Elevation share cannot be removed.
setElevationreverts for a share of 0, so after an elevation treasury share is set, its share count can change but cannot return to 0. - Pending value destination. Pending value moves only to the address it was recorded for. If that destination never pulls, the value stays reserved on the splitter.
- Direct transfers. Collateral sent to a splitter without
fetchFundsis part of the distributable amount of the nextfetchFundscall. - Who can call
fetchFunds. Any address can call it. It reverts while the market is frozen and for a zero token address or a zero amount. - Recipient list.
setRecipientsreverts for an empty list, more than 36 recipients, mismatched array lengths, a zero address, a zero share, a duplicate, or the address of the elevation treasury share’s destination. - Elevation treasury share.
setElevationreverts for the zero address, an address without code, the splitter itself, or an address that is a recipient. - Small loans. With an origination fee above 0, a loan below ⌈10,000 / rate⌉ smallest units reverts. Inside
buyAndBorrow, a round whose loan fee would round to 0 ends the loop instead. - LTV of 100%.
setLoanToValueRatioreverts at 10,000 bps and above, and at 0.
Code
Source:
house-markets/contracts at 0ebbc89a (branch integration/v12-post-qa).