Treasury
1. The fee sink
Each pool’s treasury() is a plain address, not a contract (the AccessControl.treasury pointer it is seeded from must be a contract: a rotation to an address with no code reverts NotContract). Pool.initialize seeds it from
AccessControl.treasury() and reverts on zero; it moves afterwards only through the
UPDATE_TREASURY op (GOVERNANCE tier, 7 days). Only that exact address may claim the pool’s
accrued protocol fees (Admin.claimTreasury(pool, token)). Fees accrue as pending LP shares of
each leg (Pool.treasuryShares); a claim also folds untracked balance in, up to the leg’s
liabilities, and mints the shares to the treasury as LP tokens.
Detail: Protocol Fee Collection.
2. Untrusted by design
The treasury is a pointer the owner rotates, not a principal
(Access Control §1). It is untrusted: it calls
claimTreasury and nothing else. Reserves, liabilities, LP positions and parameters are out
of its reach.
3. Rotation
The owner rotates AccessControl.treasury() through
queueRole(TREASURY) → executeRole at the GOVERNANCE tier, guardian-cancellable while pending.
previousTreasury() keeps the outgoing address payable for one GOVERNANCE delay plus the grace
period, so a pool mid-rotation still settles.
Tier durations: Access Control §3.