Manage the Vault Interest Controller (VIC)
The Vault Interest Controller (VIC) is the engine of your Vault V2's yield accounting. As a Curator
, you are responsible for setting, and if necessary, changing the VIC to ensure that the vault's reported yield accurately reflects its underlying performance.
This guide will walk you through how to set and manage a VIC for your vault, using both scripts and direct contract interactions.
Setting a Vault's Interest Controller
When your vault is first deployed, it has no VIC, meaning it won't accrue any interest. Your first step is to set one. There are two primary types of VICs available:
ManualVic
: A simple VIC where theAllocator
orCurator
manually sets the interest rate. This offers maximum flexibility but requires active management.SingleMorphoVaultV1Vic
: An automated VIC designed for vaults that allocate exclusively to a single Morpho Vault V1 via theMorphoVaultV1Adapter
. It automatically reads the Vault V1's performance.
Method 1: Setting a VIC via Script (Recommended)
The deployment repository includes VIC setup in the main deployment script: https://github.com/morpho-org/vault-v2-deployment
The DeployVaultV2.s.sol
script automatically deploys and sets a SingleMorphoVaultV1Vic
:
// Deploy the VIC (happens automatically in DeployVaultV2.s.sol)
address singleMorphoVaultV1Vic = address(new SingleMorphoVaultV1Vic(morphoVaultV1Adapter));
// Submit and execute VIC setup
vaultV2.submit(abi.encodeCall(vaultV2.setVic, (singleMorphoVaultV1Vic)));
vaultV2.setVic(singleMorphoVaultV1Vic);
For manual VIC deployment or changes after initial setup:
script/DeployAndSetVic.s.sol
pragma solidity 0.8.28;
import {Script, console} from "forge-std/Script.sol";
import {IVaultV2} from "vault-v2/interfaces/IVaultV2.sol";
import {SingleMorphoVaultV1Vic} from "vault-v2/vic/SingleMorphoVaultV1Vic.sol";
import {ManualVic} from "vault-v2/vic/ManualVic.sol";
contract DeployAndSetVic is Script {
function run() external {
address vaultAddress = vm.envAddress("VAULT_V2_ADDRESS");
address morphoVaultV1Adapter = vm.envAddress("MORPHO_VAULT_V1_ADAPTER");
IVaultV2 vault = IVaultV2(vaultAddress);
vm.startBroadcast();
// Option 1: Deploy SingleMorphoVaultV1Vic
address newVic = address(new SingleMorphoVaultV1Vic(morphoVaultV1Adapter));
// Option 2: Deploy ManualVic (uncomment if needed)
// address newVic = address(new ManualVic(vaultAddress));
// Submit the proposal
bytes memory data = abi.encodeCall(IVaultV2.setVic, (newVic));
vault.submit(data);
vm.stopBroadcast();
console.log("VIC deployed at:", newVic);
console.log("Proposal submitted. Check timelock before executing.");
}
}
Method 2: Setting a VIC via Etherscan
1. Deploy Your VIC
For SingleMorphoVaultV1Vic
:
- Go to the verified
SingleMorphoVaultV1Vic
contract on Etherscan. - Click "Write Contract" and connect your wallet.
- Deploy a new instance by clicking "Write as Proxy" and providing:
_morphoVaultV1Adapter
: Your vault's MorphoVaultV1Adapter address
For ManualVic
:
- Deploy similarly, providing:
_vault
: Your Vault V2 address
2. Submit the Proposal
- Navigate to your Vault V2 contract on Etherscan.
- Connect the Curator's wallet.
- Encode the function call:
abi.encodeCall(IVaultV2.setVic, (newVicAddress))
. - Call
submit(bytes)
with the encoded data.
3. Execute After Timelock
- Wait for the timelock period (check with
executableAt(bytes)
). - Call
setVic(address)
with the VIC address.
Managing Manual VIC Settings
If using a ManualVic
, the allocator must set the interest rate:
// As Allocator, set interest rate and deadline
ManualVic(vicAddress).setInterestPerSecondAndDeadline(
interestPerSecond, // e.g., 158549e11 for ~5% APY
deadline // Unix timestamp when rate expires
);
The curator must first set a maximum allowed rate:
// As Curator, set max interest per second
ManualVic(vicAddress).setMaxInterestPerSecond(maxRate);
Changing or Removing a VIC
To Change a VIC
Follow the same submit → wait → execute pattern with the new VIC address.
To Remove a VIC
Set the VIC to the zero address:
// Submit proposal to remove VIC
bytes memory data = abi.encodeCall(IVaultV2.setVic, (address(0)));
vault.submit(data);
// After timelock, execute
vault.setVic(address(0));