For the complete documentation index, see llms.txt. This page is also available as Markdown.

How it Works

How it works

The lifecycle of a deposit

1. You deposit           USDC ──▶ Vault ──▶ Manager
                                  (mints you shares)

2. Capital is deployed   Manager ──▶ offchain trading strategy
                                     (via whitelisted addresses)

3. Results are reported  offchain engine ──▶ Yield ──▶ Vault
                                              (share price moves)

4. You request an exit   requestRedeem() — shares burned, amount locked

5. Cooldown elapses      (1 day by default)

6. Capital returns       Manager ──▶ Vault
                                     (operator-triggered)

7. You collect           redeem() ──▶ USDC to you

Steps 3 and 6 depend on offchain actors. Everything else you control yourself.

The three contracts

The protocol is three upgradeable contracts, each with one job.

Vault (townSqToken)

The ERC-4626 token you interact with. It mints and burns shares, tracks redemption requests, and maintains the accounting that determines the share price. It deliberately does not hold assets — deposits pass straight through to the Manager.

Because of this, totalAssets() is a bookkeeping number (virtualAssets minus profit that has not vested yet), not a balance you can verify by looking at the vault's token holdings.

Manager

Custodies every deposited asset and deploys capital into the strategy. Two flows matter to you:

  • Out: an operator calls execute() to send capital to whitelisted destinations. This is how funds reach the offchain trading book.

  • In: an operator calls transferToVault() to push assets back so redemptions can be paid.

The Manager also enforces an allowlist — capital can only be sent to addresses that governance has explicitly whitelisted.

Yield

Receives the offchain engine's profit and loss reports and applies them to the vault. It handles profit vesting, loss application, and the treasury's performance fee.

Where the yield comes from

Not from onchain lending or liquidity provision. Capital is transferred to an offchain trading counterparty, and returns are generated by that counterparty's trading activity.

This has two consequences worth being explicit about:

  1. The strategy's performance is not visible onchain. The vault has no view of the trading book. What you see is the reported result.

  2. Recovering capital depends on the counterparty performing. Once assets leave via execute(), the enforcement is contractual and offchain, not onchain.

How results reach you

An offchain engine calls distributeYield(amount, feeAmount, nonce, isProfit) once per epoch — at most roughly once every 22 hours by default.

  • amount is the shareholders' slice.

  • feeAmount is the treasury's slice, on top of amount, not carved out of it.

  • isProfit sets the direction.

On profit: amount is released into the share price linearly over the vesting period (7 days by default), rather than all at once. This prevents someone from depositing just before a report and capturing yield they were not exposed to.

On loss: the loss applies immediately, with no vesting. Profit that has not vested yet absorbs the loss first — if the loss is smaller than the unvested buffer, the share price does not move at all.

Each report is bounded: by default no more than 0.5% of vault assets per epoch, and epochs must be at least ~22 hours apart. Both limits are governance-adjustable.

Last updated