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.