Skip to content

KPortfolio

Contract: KPortfolio.sol Inherits: 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

  1. Pool Manager Trust: The PoolManager role is critical — whitelisting a malicious EarnPool adapter allows that contract to steal any USDC deposited by the Trader.
  2. Bounded Iteration: totalValues() iterates over all active pools. A large number of pools could cause out-of-gas during settlement.
  3. Vault-Only Auto-Withdraw: onVaultWithdraw is restricted to calls from the KingsVault contract. An unauthorized caller could drain pool liquidity.
  4. Disable-Before-Zero: Disabling a pool with non-zero balance causes those funds to be excluded from totalValues(), understating NAV.