Slice
Reference

Security model

What the protocol defends against, how, and — just as importantly — the bugs that were found while building it.

Unaudited
Everything below describes intent and testing, not third-party verification. Read the risks →

The properties that must hold

PropertyHow it is enforced
Withdrawals never freezeNothing on the withdrawal path can be made to revert by a third party. Fee conversion degrades to deferral; protocol fees are pulled, not pushed.
You cannot capture fees you did not earnHarvests stream over seven days, and every liquidity change harvests first so there is no pending balance to sweep.
Automated swaps cannot be price-manipulatedEvery internal swap requires a 30-minute TWAP window and rejects a spot price that has diverged from it.
The owner cannot take your moneyThere is no function that withdraws user funds, mints shares, or pauses withdrawals. Parameters are bounded in the contract.

Bugs found during development

These are documented because a protocol's bug history tells you more about its risk than its feature list does.

1. Depositors could sweep pending fees

In Uniswap v4, changing a position's liquidity collects its entire accrued fee balance regardless of the size of the change. A deposit that did not harvest first had those fees netted against its own settlement — silently transferring other stakers' yield to whoever deposited next.

Caught by a test asserting a late depositor cannot profit from a round trip. Worth 0.9 tokens per round trip on a pool with 1M of depth. Fixed by harvesting before every liquidity change.

2. The same bug, one level down

When the vault swaps harvested fees through its own pool, that swap pays liquidity fees back to its own position — after the collection point. Those sat uncollected until the next deposit swept them. Fixed by collecting a second time after any internal swap.

3. A blocklisted treasury could have frozen every vault

This is the serious one. harvest() originally pushed the protocol fee to the treasury, and harvest() runs at the start of every deposit, withdrawal and compound. Arc's USDC reverts for a blocklisted address.

So if Circle had ever blocklisted the treasury address, every vault would have frozen permanently — withdrawals included. A total loss of user funds, triggerable by a third party, against an address the vault does not control.

Found by running the test suite against a fork of the real Arc chain rather than a local fixture. Fixed by accruing fees and having the treasury pull them with collectProtocolFees(), so a blocked treasury only fails its own collection.

The general rule this produced
Never push a token transfer on a code path that users depend on for exit. If a third party can make any transfer revert, and that transfer sits on the withdrawal path, they can freeze the protocol.

How it is tested

  • 79 tests, with the core suites run twice — once for each ordering of the token pair, since roughly half the branches depend on which side USDC sorts to.
  • Fork tests against live Arc, using the real Uniswap PoolManager and the real USDC contract. This is what caught the freeze bug.
  • Property fuzzing at 100,000 runs on the invariant that a deposit and withdrawal round trip can never return more than it took in.
  • A blocklist simulation reproducing Arc's USDC behaviour offline, so freeze-resistance is a permanent regression test rather than a one-off check.

What is deliberately out of scope

  • Impermanent loss. Not hedged. Full AMM exposure, by design.
  • A blocklisted vault. Unrecoverable, and no contract design prevents it.
  • Chain or Uniswap failure. Outside anything Slice can control.