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)
Key view functions
function getEstimatedCost(string memory modelId) external view returns (uint256);
function getEndUserPrice(string memory modelId) external view returns (uint256);
function grossMarginBps() external view returns (uint16);
function epochDuration() external view returns (uint256);
End-user markup
grossMarginBps lets governance quote users above raw infrastructure cost:
endUserPrice = cost + (cost * grossMarginBps / 10000)
That markup is separate from the router's deposit logic. The router still routes actual collected fees using cost-plus logic.
InfrastructureReserve
InfrastructureReserve holds accrued infrastructure obligations and records payments to providers.
Per-model accounting
mapping(string => uint256) public accrued;
mapping(string => uint256) public paid;
mapping(string => address) public provider;
Key functions
function deposit(string memory modelId, uint256 amount) external;
function batchDeposit(string[] memory modelIds, uint256[] memory amounts) external;
function payInfrastructureCost(
string memory modelId,
address payee,
uint256 amount,
bytes32 invoiceHash,
string memory memo
) external;
function batchPayInfrastructureCosts(Payment[] memory payments) external;
Payment transparency
Every manual payment records:
- model ID
- payee
- amount
- invoice hash
- memo
- payer
That creates an on-chain audit trail for infrastructure spending.
Worked examples
Oracle path
Oracle cost: 4 USDC per 1000 calls
Usage fee collected: 5 USDC
Call count: 1000
Infrastructure = (4 * 1000) / 1000 = 4 USDC
Profit = 5 - 4 = 1 USDC
Result:
4 USDCaccrues inInfrastructureReserve1 USDCis deposited to the AMM reserve
Fallback path
No oracle entry
infrastructureAccrualBps = 8000
Usage fee collected: 10 USDC
Infrastructure = 10 * 8000 / 10000 = 8 USDC
Profit = 2 USDC
Result:
8 USDCaccrues inInfrastructureReserve2 USDCis deposited to the AMM reserve
Canonical framing
- Do NOT distribute fees to stakers. No staking mechanism exists.
- Do NOT distribute API fees to a protocol treasury. No protocol treasury exists for API fees.
- AMM trade fees and API usage fees are separate flows.