KPortfolio
Contract:
KPortfolio.solInherits: AccessControl, Pausable
Overview
KPortfolio is the fund-routing contract that sits between KingsVault and the individual EarnPool adapters. It holds idle USDC, manages the whitelist of active pools, and provides the totalValues() aggregation used during settlement.
KingsVault never interacts with EarnPools directly — all fund dispatching flows through KPortfolio.
Roles
| Role | Permissions |
|---|---|
ROLE_POOL_MANAGER |
enablePool(), disablePool() |
ROLE_TRADER |
depositPool(), withdrawPool() |
VAULT (contract) |
onVaultWithdraw() — triggered automatically during user redemption |
Read Functions
| Function | Signature | Returns | Description |
|---|---|---|---|
totalValues |
totalValues() → uint256 |
Total USDC value | Sum of all enabled pool balances + idle USDC in Portfolio |
frictionCosts |
frictionCosts() → uint256 |
Estimated unwinding cost | Estimated slippage/cost to liquidate all positions |
activePools |
activePools() → address[] |
Pool list | Array of currently enabled EarnPool addresses |
isPoolEnabled |
isPoolEnabled(address) → bool |
Status | Whether a given pool address is in the active whitelist |
Write Functions
| Function | Signature | Role | Description |
|---|---|---|---|
enablePool |
enablePool(address pool) |
ROLE_POOL_MANAGER |
Add a new EarnPool to the whitelist |
disablePool |
disablePool(address pool) |
ROLE_POOL_MANAGER |
Remove an EarnPool from the whitelist |
depositPool |
depositPool(address pool, uint256 amount) |
ROLE_TRADER |
Allocate USDC from Portfolio idle to an enabled pool |
withdrawPool |
withdrawPool(address pool, uint256 amount) |
ROLE_TRADER |
Retrieve USDC from an enabled pool back to Portfolio |
onVaultWithdraw |
onVaultWithdraw(uint256 amount) |
VAULT only |
Auto-replenish: withdraw from pools to cover a user redemption shortfall |
Fund Flow
User deposits USDC → KingsVault → KPortfolio (idle)
│
Trader calls │
depositPool() │
┌───────────────┤
▼ ▼
EarnPool:Aave EarnPool:Morpho
(target 80%) (target 20%)
On withdrawal, if vault idle is insufficient:
User redeems shares → KingsVault.redeem()
│
▼
KPortfolio.onVaultWithdraw(shortage)
│
┌────┴─────┐
▼ ▼
Pool (primary) Pool (fallback)
│ │
└──────────┘
│
▼
USDC → KingsVault → User
Security Considerations
- Pool Manager Trust: The PoolManager role is critical — whitelisting a malicious EarnPool adapter allows that contract to steal any USDC deposited by the Trader.
- Bounded Iteration:
totalValues()iterates over all active pools. A large number of pools could cause out-of-gas during settlement. - Vault-Only Auto-Withdraw:
onVaultWithdrawis restricted to calls from the KingsVault contract. An unauthorized caller could drain pool liquidity. - Disable-Before-Zero: Disabling a pool with non-zero balance causes those funds to be excluded from
totalValues(), understating NAV.