Usage Fee Routing & InfrastructureReserve
API usage fees are routed with a cost-plus model:
- Estimated infrastructure cost is paid first
- Residual profit is deposited into the AMM reserve
- API usage fees do not flow to a protocol treasury
This flow is implemented by UsageFeeRouter, InfrastructureCostOracle, and InfrastructureReserve.
Overview
UsageFeeRouter
UsageFeeRouter receives usage-fee deposits from authorized fee depositors and splits each deposit between infrastructure and profit.
Primary path: cost-plus
If the oracle has a cost estimate for the model:
uint256 costPer1000Calls = costOracle.getEstimatedCost(modelId);
uint256 estimatedCost = (costPer1000Calls * callCount) / 1000;
infrastructureAmount = estimatedCost > amount ? amount : estimatedCost;
profitAmount = amount - infrastructureAmount;
costPer1000Callsis denominated in USDC with 6 decimalscallCountis supplied with the deposit- Infrastructure cost is capped at the deposited amount
- Remaining amount becomes profit for token holders
Fallback path: percentage split
If the oracle has no entry for the model, the router falls back to the model's infrastructureAccrualBps in HokusaiParams.
uint16 infraBps = params.infrastructureAccrualBps();
infrastructureAmount = (amount * infraBps) / 10000;
profitAmount = amount - infrastructureAmount;
The router emits a CostBasis value to show which path was used:
ORACLEPERCENTAGE_FALLBACK
Key functions
function depositFee(string memory modelId, uint256 amount, uint256 callCount) external;
function batchDepositFees(
string[] memory modelIds,
uint256[] memory amounts,
uint256[] memory callCounts
) external;
function calculateFeeSplit(
string memory modelId,
uint256 amount,
uint256 callCount
) external view returns (
uint256 infrastructureAmount,
uint256 profitAmount,
CostBasis costBasis
);
Key events
event FeeDeposited(
string indexed modelId,
address indexed poolAddress,
uint256 totalAmount,
uint256 infrastructureAmount,
uint256 profitAmount,
address indexed depositor
);
event BatchDeposited(
uint256 totalAmount,
uint256 totalInfrastructure,
uint256 totalProfit,
uint256 modelCount,
address indexed depositor
);
event FeeSplitCalculated(
string indexed modelId,
uint256 totalFee,
uint256 infraShare,
uint256 profitShare,
uint256 callCount,
CostBasis costBasis
);
InfrastructureCostOracle
InfrastructureCostOracle stores estimated infrastructure cost per 1000 API calls for each model.
What it stores
- Active cost per 1000 calls:
_costPerThousandCalls[modelId] - Pending updates with delayed activation
- Global
grossMarginBpsfor end-user pricing markup
Pricing stability
- Default epoch duration: 30 days
- Updates are queued by
GOV_ROLE - After the required epoch boundary, anyone can call
applyPendingUpdate(modelId)