Waterfalls
A waterfall is a priority of payments: an ordered list of steps sharing out a pot of cash. Each step takes what it is owed, up to what is left, and the remainder passes down.
It is how a securitisation pays its tranches, how a fund pays a preferred return before carry, and how a project pays lenders before equity.
The shape
waterfall deal.distribution on entity asset.trust {
schedule every month from 2026-01 to 2030-12
from asset.trust.available_funds
pay servicing to party.servicer = 12500.0
pay senior to asset.class_a = 6250.0
pay residual to party.certificate = remaining
}Three parts:
on entity— whose cash this is.schedule— when it runs. The same construct a stream takes.from— the pot.
Then the steps, in the order they are paid.
One form for every step
A step is pay <name> to <payee> = <expr>. There is no separate syntax per kind
of payment, because every kind is arithmetic:
| what you want | how to write it |
|---|---|
| a fixed amount | = 12500.0 |
| capped at a limit | = min(fee, cap) |
| pay a balance down to a target | = asset.class_a.balance - asset.trust.pool_balance |
| top an account up to a level | = inputs.specified_reserve - asset.reserve.balance |
| only on a certain date | = if(time.t >= 24, balance, 0.0) |
| an earlier step's shortfall | = owed.trustee_fee - paid.trustee_fee |
| everything left | = remaining |
Three names a step can read
On top of everything an ordinary expression sees:
remaining | what is still in the pot at this step |
paid.<step> | what an earlier step actually paid |
owed.<step> | what an earlier step would have paid, unbounded |
A step also reaches any other entity's declared properties by naming it —
asset.class_a.original_balance — which is how one tranche's step reads
another's balance. entity.asset.class_a.original_balance is the same read
spelled the long way.
owed and paid differ exactly when a step could not be paid in full, so their
difference is the shortfall. That is how a capped fee gets its overflow paid
later, and how a step measures a balance "after giving effect to" the payments
above it.
A step may only read steps declared before it. Reading a later one is a compile error, because a priority of payments is an order, not a system of equations.
The pot never goes negative
Every step pays min(max(0, your expression), remaining).
You do not have to write min(..., remaining) yourself, and a step that asks
for more than is left simply takes what is left. A negative expression pays
nothing rather than clawing cash back.
That also makes = remaining mean exactly what it says.
Say where the remainder goes
At least one step must read remaining, or the model does not compile.
Without it, whatever survives the last step would vanish with nothing to show for it. Naming the residual is the difference between a model that says the sponsor keeps the excess and one that quietly loses it.
When it runs
A waterfall is a post-cash-flow distribution: it runs after the period's streams and states are known, so it allocates money that already exists. It never feeds a stream in the same period.
Two shapes cover most deals, and a model can use both at once:
// Every period — a distribution date, a debt service cascade.
schedule every month from 2026-01 to 2030-12
// Once — an exit, a liquidation, a final recoupment.
schedule on 2030-12What comes out
Each step publishes as a series named stream.<waterfall>.<step>, and its cash
counts toward the payee's total. A waterfall is not a separate kind of output:
statements, metrics and the results document read it the way they read anything
else.
One waterfall's output as another's pot
Because steps publish as series, a later waterfall can draw on an earlier one:
waterfall fund.distribution on entity asset.fund {
schedule on 2025-01
from inputs.proceeds
pay carry to party.gp = remaining * 0.20
pay lp_share to party.lp = remaining
}
waterfall firm.carry_split on entity asset.mgmt_co {
schedule on 2025-01
from series_sum("fund.distribution.carry", 0, 5)
pay team_pool to party.team = remaining * 0.40
pay firm_share to party.founders = remaining
}The rule is the same order that governs steps: a waterfall may read any waterfall declared before it. That is what a fund carry rolling into a management company and out again to a stakeholder needs, and it keeps the second pot as a computed number rather than an assumption holding a stale copy of it.
Worked structures
Six real waterfalls are encoded in the test suite, and between them they use only the rules above.
A 22-step consumer ABS priority of payments — servicer and trustee ahead of the notes, five rated classes taking interest then principal in strict seniority, a reserve topped to its specified level, an overcollateralisation target, and a certificateholder taking what survives.
A private fund carry waterfall — capital back, a compounding 8% preferred return, a full GP catch-up, then 80/20. It reproduces its published figures exactly, and one definition covers three published structures: the only thing separating them is what the catch-up is computed on, which is an argument.
An LBO exit split — the sponsor's converted preferred against management's rollover and exercised options.
An IRR-hurdle waterfall — three participants whose vested percentages step up as the LP's return crosses eight hurdles.
A GP stakes nested split — a fund waterfall, then the management company's split with the deal team, then the founders against a passive minority investor. Three waterfalls, each drawing on the one above.
A partial catch-up — the same fund waterfall where the GP takes half of each dollar above the preferred instead of all of it. Set the catch-up rate to 1 and it returns the full catch-up's numbers exactly; the two structures are one expression with a different argument.
On hurdles and catch-ups
Both of the last two are commonly said to need an iterative solver. Neither does, and the reason is worth knowing before you reach for one.
A catch-up that pays the GP 20% of everything distributed in two tiers
combined is X / (pref + X) = 0.20, so X = pref / 4. One division.
An IRR hurdle does not solve for a rate — the rate is an input. What is unknown is the payment that reaches it, and present value is linear in a payment at a fixed rate. Where a hurdle also selects among tiers, the thresholds are computable in advance and choosing between them is an ordered comparison.
So a waterfall step stays an expression, and the language needs no solver to carry these structures.
Related
- The object model — assets, parties and the entities a waterfall pays.
- Reading results — where the per-step series land.