Crypto Fund Infrastructure Development
A crypto fund is not just "multisig + trading account on exchange". Once a fund has multiple LPs, questions arise: how is NAV calculated in real-time, how to ensure LP asset isolation, how to automate redemption without manual intervention, how to ensure audit trails for every operation. Fund infrastructure is a complex of smart contracts, off-chain services, and operational processes. Let's break it down by layers.
Architecture: What fund infrastructure includes
A typical crypto fund consists of several technical layers:
On-chain layer (smart contracts):
- Vault contract — asset custody, LP share accounting
- NAV oracle — feeding current asset valuation on-chain
- Subscription/Redemption contract — managing LP entry/exit
- Fee module — calculation and collection of management and performance fees
Off-chain layer:
- NAV calculator — price aggregation, portfolio valuation
- Trade execution engine — order execution via CEX/DEX
- Reporting pipeline — reports for LPs and regulators
- Risk monitoring — position monitoring, drawdown, exposure
Operational layer:
- Multi-sig for governance — Gnosis Safe with signer policies
- Key management — hardware security modules (HSM) or MPC wallets
- Audit trail — immutable log of all operations
Vault contract: LP share accounting
EIP-4626 (Tokenized Vault Standard) is the starting point for most on-chain funds. Defines interface deposit/withdraw/mint/redeem with ERC-20 shares:
// Simplified vault structure
contract FundVault is ERC4626, AccessControl {
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
bytes32 public constant NAV_ORACLE_ROLE = keccak256("NAV_ORACLE_ROLE");
uint256 private _reportedNavPerShare; // NAV per share, updated by oracle
uint256 public lastNavUpdate;
uint256 public constant NAV_STALENESS_THRESHOLD = 24 hours;
// Override totalAssets() to account for off-chain assets
function totalAssets() public view override returns (uint256) {
require(
block.timestamp - lastNavUpdate <= NAV_STALENESS_THRESHOLD,
"NAV is stale"
);
return _reportedNavPerShare * totalSupply() / 1e18;
}
// NAV oracle updates portfolio valuation
function updateNAV(uint256 newNavPerShare) external onlyRole(NAV_ORACLE_ROLE) {
require(newNavPerShare > 0, "Invalid NAV");
_reportedNavPerShare = newNavPerShare;
lastNavUpdate = block.timestamp;
emit NAVUpdated(newNavPerShare, block.timestamp);
}
}
Key complexity: totalAssets() in EIP-4626 assumes assets are inside the contract. For a fund with positions on CEX, in DeFi protocols, in BTC — assets are distributed. NAV oracle must aggregate all sources and feed single on-chain value.
Subscription and Redemption: Liquidity management
Simple deposit/withdraw from EIP-4626 doesn't work for funds with periodic liquidity windows. Real scheme:
Subscription queue. LP submits subscribeRequest(amount) + transfers USDC. Request is queued. End of period (e.g., weekly), manager processes queue: calculates shares by current NAV, mints them to LP.
Redemption queue. Similarly: redeemRequest(shares), shares locked, payment at period end. Lock-up period (typically 30-90 days) enforced via timestamp check.
struct RedemptionRequest {
address lp;
uint256 shares;
uint256 requestedAt;
bool processed;
}
mapping(uint256 => RedemptionRequest) public redemptionQueue;
uint256 public redemptionQueueHead;
uint256 public redemptionQueueTail;
function requestRedemption(uint256 shares) external {
require(shares > 0 && balanceOf(msg.sender) >= shares);
// Lock-up: cannot redeem sooner than lockupPeriod
require(
block.timestamp >= subscriptionTimestamp[msg.sender] + lockupPeriod,
"Lock-up period active"
);
_transfer(msg.sender, address(this), shares); // lock shares
redemptionQueue[redemptionQueueTail++] = RedemptionRequest({
lp: msg.sender,
shares: shares,
requestedAt: block.timestamp,
processed: false
});
}
NAV Calculator: Portfolio Valuation
This is the most complex off-chain component. NAV must accurately reflect the value of all fund assets at calculation time.
Data sources for NAV:
| Asset type | Price source | Nuances |
|---|---|---|
| Spot on CEX (Binance, Bybit) | Exchange REST API, mid-price | Account for bid-ask spread on large positions |
| DeFi positions (Uniswap v3, Aave) | On-chain via multicall | For LP positions — impermanent loss |
| Locked staking | On-chain balance + accrued rewards | Rewards often off-chain until claim |
| OTC/illiquid | Manual valuation or TWAP | Requires governance process |
| BTC | Chainlink, Pyth or aggregator | Multiple sources for manipulation resistance |
NAV manipulation — serious threat. If NAV depends on single price source, flash loan attack on DEX pool can temporarily distort price and give attacker arbitrage through subscription/redemption. Protection: time-weighted average price (TWAP) instead of spot, multiple source aggregation, circuit breaker on sharp NAV changes.
class NAVCalculator:
async def calculate_nav(self) -> Decimal:
positions = await self.fetch_all_positions()
nav = Decimal('0')
for position in positions:
price = await self.get_robust_price(position.asset)
nav += position.quantity * price
# Verify: NAV change must not exceed threshold
prev_nav = await self.get_last_nav()
change_pct = abs(nav - prev_nav) / prev_nav * 100
if change_pct > self.MAX_NAV_CHANGE_PCT:
await self.trigger_circuit_breaker(nav, prev_nav, change_pct)
raise NAVCircuitBreakerError(f"NAV change {change_pct:.1f}% exceeds threshold")
return nav
async def get_robust_price(self, asset: str) -> Decimal:
prices = await asyncio.gather(
self.chainlink.get_price(asset),
self.pyth.get_price(asset),
self.cex_api.get_mid_price(asset),
)
# Median from three sources
valid = [p for p in prices if p is not None]
return sorted(valid)[len(valid) // 2]
Fee Module: Management and Performance fees
Management fee (typically 1-2% annually) accrues continuously. Implementation via minting new shares to manager:
// Management fee: mint shares proportional to elapsed time
function accrueManagementFee() public {
uint256 elapsed = block.timestamp - lastFeeAccrual;
if (elapsed == 0) return;
// fee = totalSupply * feeRate * elapsed / YEAR
uint256 feeShares = totalSupply() * managementFeeRate * elapsed
/ (10000 * 365 days);
if (feeShares > 0) {
_mint(feeRecipient, feeShares);
lastFeeAccrual = block.timestamp;
emit ManagementFeeAccrued(feeShares);
}
}
Performance fee (typically 20% of profit) calculated via High Water Mark (HWM) — fee taken only on profit above previous NAV peak. This protects LPs from double taxation after drawdown and recovery.
uint256 public highWaterMark; // NAV per share at previous peak
function settlePerformanceFee(uint256 currentNavPerShare) external onlyRole(MANAGER_ROLE) {
if (currentNavPerShare <= highWaterMark) return; // No profit above HWM
uint256 profit = currentNavPerShare - highWaterMark;
uint256 feePerShare = profit * performanceFeeRate / 10000;
// Convert to shares and mint to manager
uint256 feeShares = feePerShare * totalSupply() / currentNavPerShare;
_mint(feeRecipient, feeShares);
highWaterMark = currentNavPerShare;
emit PerformanceFeeSettled(feePerShare, feeShares);
}
Key Management and Security
Gnosis Safe — standard for multi-sig fund governance. Threshold policies: 3-of-5 for major operations (withdrawal > $1M), 2-of-3 for daily operations.
MPC wallets (Fireblocks, Copper, Liminal) — alternative to multi-sig for institutional funds. Key never fully assembled, protecting against single participant compromise. Even more important: MPC enables approval workflow integration — each transaction passes compliance check before signing.
HSM (Hardware Security Module) — for maximum hot wallet security. AWS CloudHSM or physical HSMs (Thales, Utimaco).
Isolation principles:
- Cold storage (multisig on air-gapped devices) — long-term assets, > 70% AUM
- Warm storage (MPC/HSM) — working capital for trading
- Hot wallet — minimum for gas fees and small operations
Reporting and Auditability
LPs expect: monthly NAV statements, trade logs, fee calculations. Regulators in some jurisdictions (Caymans, BVI) require independent NAV valuation and annual audit.
All critical operations written to immutable event log:
- Every NAV change with data sources and calculation
- Every trade with execution price, commission, counterparty
- Every subscription/redemption with NAV at processing time
Storage: PostgreSQL for operational access + Arweave/IPFS for immutable archive + on-chain hashes of key reports for verification.
Technology Stack
| Component | Technology |
|---|---|
| Vault contract | Solidity, EIP-4626, OpenZeppelin |
| Trade execution | Python, ccxt (CEX), viem (DEX) |
| NAV calculator | Python, async, Chainlink/Pyth |
| Key management | Fireblocks MPC or Gnosis Safe |
| Database | PostgreSQL + TimescaleDB |
| Monitoring | Prometheus + Grafana + PagerDuty |
| Reporting | Python + LaTeX PDF generator |
Development Process
Phase 1 (1 week): Design. Define asset types, subscription/redemption windows, fee structure, regulatory reporting needs, threat models.
Phase 2 (2-3 weeks): Smart contracts. Vault, NAV oracle, fee module. Testing on Foundry (fuzz tests, invariant tests). Formal verification of key invariants.
Phase 3 (2-3 weeks): Off-chain infrastructure. NAV calculator, trade execution engine, reporting pipeline.
Phase 4 (1 week): Integration and testing. End-to-end tests on testnet, NAV oracle stress testing.
Phase 5 (1 week): Audit and deploy. External smart contract audit, gradual rollout with limits.
Total: 7-10 weeks for full infrastructure. Minimal version (vault + NAV + multi-sig without automation) — 3-4 weeks.







