Overview
The StrategyRouter contract orchestrates multiple yield strategies, handling allocation rebalancing, harvest operations, and strategy-level fund management. It acts as the intermediary between the Vault and individual Strategy contracts.
Inherits: Ownable
State Variables
Immutable. Reference to the Vault contract that holds user funds.
Dynamic array of active strategy contract addresses.
targetBps
mapping(address => uint256)
required
Target allocation for each strategy in basis points. Sum must equal 10000 (100%).
Events
StrategiesUpdated
event StrategiesUpdated()
Emitted when the strategy list and allocations are updated.
Rebalanced
event Rebalanced(uint256 totalManaged)
Total assets under management after rebalancing
Harvested
event Harvested(address indexed strat, uint256 profit)
Strategy address that was harvested
Amount of profit harvested from the strategy
WithdrawnFromStrategies
event WithdrawnFromStrategies(uint256 requested, uint256 pulled)
Amount requested by vault
Actual amount withdrawn from strategies
DeleverageTriggered
event DeleverageTriggered(address indexed strat, uint256 maxLoops)
Strategy being deleveraged
Maximum deleverage iterations allowed
StrategyWithdrawFailed
event StrategyWithdrawFailed(address indexed strat, string reason)
Error message describing the failure
Constructor
constructor(address _vault, address _owner) Ownable(_owner)
Address of the Vault contract
Address that will own this router contract
Strategy Management
setStrategies
function setStrategies(
address[] calldata _strats,
uint256[] calldata _bps
) external onlyOwner
Set or update the list of strategies and their target allocations.
Array of strategy contract addresses
Array of target allocations in basis points (must sum to 10000)
Requirements:
- Arrays must have same length
- No zero addresses allowed
- Sum of
_bps must equal 10000 (100%)
Example:
address[] memory strats = new address[](2);
strats[0] = address(strategyAave);
strats[1] = address(strategyAaveLeverage);
uint256[] memory allocations = new uint256[](2);
allocations[0] = 6000; // 60% to Aave
allocations[1] = 4000; // 40% to AaveLeverage
router.setStrategies(strats, allocations);
getStrategies
function getStrategies() external view returns (address[] memory)
Get the list of active strategy addresses.
Array of strategy contract addresses
getStrategyStats
function getStrategyStats(address strat)
external view
returns (
uint256 balance,
uint256 target,
uint256 actualPct
)
Get detailed statistics for a specific strategy.
Strategy address to query
Current balance held by the strategy
Target allocation in basis points
Actual allocation percentage in basis points
getPortfolioState
function getPortfolioState()
external view
returns (
address[] memory strats,
uint256[] memory balances,
uint256[] memory targets
)
Get complete portfolio state for all strategies.
Array of strategy addresses
Current balance in each strategy
Target allocation for each strategy in basis points
Fund Management
moveFundsToStrategy
function moveFundsToStrategy(address strat, uint256 amount) external onlyOwner
Manually move funds from vault to a specific strategy and invest them.
Strategy to receive funds
Example:
// Move 10000 USDC to Aave strategy
router.moveFundsToStrategy(address(strategyAave), 10000e6);
moveAllToStrategy
function moveAllToStrategy(address strat) external onlyOwner
Move all available vault assets to a specific strategy.
Strategy to receive all funds
withdrawFromStrategies
function withdrawFromStrategies(uint256 amount) external returns (uint256)
Withdraw assets from strategies to satisfy vault withdrawal requests. Called by Vault only.
Amount needed by the vault
Actual amount withdrawn from strategies
Requirements:
- Only callable by the Vault contract
- Will iterate through strategies until requested amount is satisfied
- Reverts if insufficient liquidity across all strategies
Behavior:
- Iterates through strategies in order
- Calls
withdrawToVault() on each strategy
- Measures actual amount received (handles strategies that return different amounts)
- Continues until requested amount is satisfied or strategies exhausted
Rebalancing
rebalance
function rebalance() external onlyOwner
Rebalance all strategies to match target allocations.
Process:
- Calculate current total managed assets
- Withdraw excess from overweight strategies
- Recalculate total after withdrawals
- Deploy funds to underweight strategies
Error Handling:
- Continues rebalancing other strategies if one fails
- Emits
StrategyWithdrawFailed event for failed operations
Example:
// After market movements, rebalance to target allocations
router.rebalance();
Harvesting
harvestAll
function harvestAll() external onlyOwner
Harvest profits from all strategies and route to vault.
Process:
- Iterates through all strategies
- Calls
harvest() on each strategy
- Measures profit returned to vault
- Calls
vault.handleHarvestProfit() to apply performance fees
Error Handling:
- Continues harvesting other strategies if one fails
- Emits events for both successes and failures
Example:
// Daily harvest operation
router.harvestAll();
// Profit automatically sent to vault and fees deducted
Risk Management
triggerDeleverage
function triggerDeleverage(address strat, uint256 maxLoops) external onlyOwner
Manually trigger deleveraging on a leveraged strategy (e.g., during high volatility).
Address of the strategy to deleverage
Maximum number of deleverage iterations (gas limit protection)
Use Cases:
- Market volatility increases liquidation risk
- Preparing to withdraw large amounts from leveraged strategies
- Emergency risk reduction
Example:
// Deleverage the Aave leverage strategy in up to 5 loops
router.triggerDeleverage(address(strategyAaveLeverage), 5);
Integration Example
// 1. Deploy router
StrategyRouter router = new StrategyRouter(
address(vault),
owner
);
// 2. Connect vault to router
vault.setRouter(address(router));
// 3. Setup strategies
address[] memory strats = new address[](3);
strats[0] = address(strategyAave);
strats[1] = address(strategyAaveLeverage);
strats[2] = address(strategyCompound);
uint256[] memory allocations = new uint256[](3);
allocations[0] = 5000; // 50% Aave
allocations[1] = 3000; // 30% Aave Leverage
allocations[2] = 2000; // 20% Compound
router.setStrategies(strats, allocations);
// 4. Deploy funds
router.moveFundsToStrategy(strats[0], 50000e6);
router.moveFundsToStrategy(strats[1], 30000e6);
router.moveFundsToStrategy(strats[2], 20000e6);
// 5. Regular operations
router.harvestAll(); // Collect profits
router.rebalance(); // Maintain target allocations
// 6. Check portfolio state
(address[] memory s, uint256[] memory balances, uint256[] memory targets) =
router.getPortfolioState();
for (uint i = 0; i < s.length; i++) {
console.log("Strategy:", s[i]);
console.log("Balance:", balances[i]);
console.log("Target:", targets[i]);
}
AI Integration
The StrategyRouter is designed to be controlled by MetaVault AI agents:
// AI agent monitors market conditions
if (marketVolatility > threshold) {
// Reduce leverage exposure
router.triggerDeleverage(leveragedStrategy, 3);
// Rebalance to safer allocations
router.setStrategies(
[safeStrategy, moderateStrategy],
[8000, 2000] // 80% safe, 20% moderate
);
router.rebalance();
}
// AI determines optimal harvest timing
if (estimatedGas < gasThreshold && estimatedProfit > minProfit) {
router.harvestAll();
}
Security Considerations
- Owner Control: Owner has significant control. Use multisig or timelock.
- Strategy Failures: Individual strategy failures don’t brick the router.
- Rebalance Ordering: Strategies are processed in array order - consider liquidity.
- Gas Limits: Large strategy arrays may hit gas limits in
harvestAll() or rebalance().
See Also