Skip to content
3F Docs

Fund

The Fund module is Grunt’s adapter layer for protocols that settle asynchronously. It wraps external protocols — like Bitwise’s USCC Crypto Carry Fund — behind a predictable state machine, so the Facility can interact with them through a consistent interface regardless of how the underlying protocol works.

ERC-7540 is an existing standard for asynchronous vaults. At first glance, it seems like it should fit Grunt’s needs. In practice, it falls short in three critical ways:

No recovery path. If an external protocol rejects a subscription or returns funds for any reason, ERC-7540 has no explicit mechanism to recover those funds. In Grunt, where capital is pooled from multiple LPs and combined with bridge loans, the inability to recover from a failed operation is unacceptable.

No pre-funding stage. In ERC-7540, the request itself is where funds are transferred. There is no way to validate or confirm the request before committing capital. Grunt needs to be able to create an order, have it verified (for example, passing KYC/AML checks on the receiving end), and only then commit the capital.

No partial recovery. When an external protocol returns funds, it may do so across multiple transactions — for example, if a redemption settles in batches over several days. ERC-7540 has no built-in support for tracking and collecting partial returns.

The IFund interface addresses all three of these gaps.

Every fund order follows a state machine with clearly defined transitions. This gives the Facility a predictable model for managing async operations, regardless of how unpredictable the underlying protocol might be.

EMPTY — No order exists. This is the default starting state.

PENDING — An order has been recorded, but it has not yet been approved by the external protocol. No assets have been transferred. This state exists for protocols that require verification before accepting funds (for example, KYB/KYC checks or deposit limit validation).

ACCEPTED — The order has been approved and is ready to receive assets. The Facility can now commit capital to it. If the order needs to be abandoned before committing, it can be cancelled back to EMPTY.

PROCESSING — Assets have been committed and the external protocol is processing the operation. This is the “waiting for settlement” state. The Facility cannot intervene; it must wait for the external protocol to complete.

UNLOCKING — The operation succeeded. The resulting assets (e.g., wrapped fund shares for a deposit, or stablecoins for a redemption) are ready to be claimed. The Facility calls unlock to transfer them.

RECOVERING — The operation failed or was rejected after commitment. The assets (or whatever the protocol returned) need to be reclaimed. The Facility calls recover to retrieve them. Recovery may require multiple calls if assets are returned in batches.

ENDED — Terminal state. The order lifecycle is complete, whether through successful unlock or recovery.

stateDiagram-v2
    [*] --> EMPTY
    EMPTY --> PENDING : create()
    EMPTY --> ACCEPTED : create()
    PENDING --> ACCEPTED : cleared
    ACCEPTED --> EMPTY : cancel()
    ACCEPTED --> PROCESSING : commit()
    PROCESSING --> UNLOCKING : success
    PROCESSING --> RECOVERING : failure
    UNLOCKING --> ENDED : unlock()
    RECOVERING --> ENDED : recover()
    ENDED --> [*]

Each order operates in one of two modes:

  • Deposit mode — the input is a liquid asset (e.g., USDC) and the output is a wrapped fund share (e.g., wUSCC)
  • Redeem mode — the input is a wrapped fund share (e.g., wUSCC) and the output is a liquid asset (e.g., USDC)

When the Facility subscribes to an on-chain fund, it receives a receipt token — for example, USCC from Bitwise. This receipt token needs to become collateral in a lending market so the protocol can borrow against it and repay the bridge loan.

But there is a problem: if the receipt token is freely usable, anyone could take it to any lending venue, post it as collateral, and borrow against it outside of Grunt’s guardrails. This would bypass the compliance controls, health factor management, and liquidation protections that the protocol is designed to enforce.

The solution is wrapped assets. Instead of using USCC directly, Grunt wraps it into wUSCC — a 1:1 wrapper token that the protocol controls. The wrapped token can only be minted and burned through the Fund wrapper, and its transfer rules are governed by the protocol’s TransferGuard.

This means:

  • wUSCC can only be used as collateral in Grunt-approved Borrow Positions
  • Transfers of wUSCC are subject to compliance checks (blocklist/whitelist)
  • The protocol maintains full visibility into where its collateral is deployed
  • No one can take the underlying receipt tokens outside the protocol’s control

The wrapping does not change the economic value — 1 wUSCC always represents exactly 1 USCC. It only changes who controls where the token can go.

Bitwise is a regulated issuer of tokenized funds. Their USCC token represents ownership in the Bitwise Crypto Carry Fund, which provides qualified purchasers access to crypto basis and cash-and-carry strategies. Here is how the Fund module integrates with it:

  1. Create — the Facility creates a deposit order on the USCC Fund wrapper
  2. Commit — the Facility transfers USDC to Bitwise’s designated recipient. The order moves to PROCESSING
  3. Wait — Bitwise processes the subscription off-chain (typically T+1 to T+3)
  4. Unlock — once Bitwise mints USCC on-chain, the Fund wrapper wraps it into wUSCC and transfers it to the Facility. The order moves to ENDED
  1. Create — the Facility creates a redeem order on the USCC Fund wrapper
  2. Commit — the Fund wrapper burns the wUSCC, unwraps the underlying USCC, and initiates a redemption with Bitwise. The order moves to PROCESSING
  3. Wait — Bitwise processes the redemption off-chain
  4. Unlock — once USDC is returned, the Fund wrapper transfers it to the Facility. The order moves to ENDED
  5. Or recover — if Bitwise rejects the redemption, the Fund wrapper re-wraps the returned USCC into wUSCC and the Facility recovers it

The state machine ensures that every possible outcome — success, failure, partial return — has an explicit, predictable handling path.