Create a Morpho Vault V2
Deploying a Morpho Vault V2 is a permissionless process that anyone can initiate. This guide covers three methods for deploying your vault, ranging from the simplest user-friendly interface to more advanced technical approaches.
This guide covers three methods for deploying your vault:
- Using the Curator App (Recommended): The easiest and most user-friendly method with a graphical interface for vault creation and configuration.
- Using a Deployment Script: A powerful and efficient method for developers, allowing you to create, configure, and assign roles for your vault in a single, automated process.
- Using Etherscan: A manual approach suitable for those who prefer interacting directly with contracts on a block explorer.
Method 1: Create a Vault via the Curator App
The Curator App provides the easiest and most user-friendly way to deploy a Morpho Vault V2. This web-based interface guides you through the entire vault creation process without requiring any coding or command-line experience.
Curator App: https://curator.morpho.org/vaults
Why Use the Curator App?
- No Technical Knowledge Required: User-friendly graphical interface suitable for all experience levels.
- Guided Setup: Step-by-step wizard walks you through every configuration option.
- Instant Deployment: Deploy your vault directly from your browser using your connected wallet.
- Built-in Validation: Automatic validation of parameters to prevent common configuration mistakes.
- Visual Configuration: Easily configure roles, adapters, and risk parameters through intuitive forms.
Getting Started with the Curator App
1. Connect Your Wallet
Navigate to https://curator.morpho.org/vaults and connect your Ethereum wallet (e.g., MetaMask, WalletConnect).
2. Select Network
Choose the network where you want to deploy your vault. Morpho Vault V2 is available on multiple networks including Ethereum mainnet, Base, and other supported chains.
3. Configure Vault Parameters
You will first be asked to set the main vault's parameters:
- Asset: Select the ERC-20 token your vault will use (e.g., USDC, WETH).
- Owner: Set the initial owner address (ideally a multisig for security).
Once the vault created, set and abdicate the Morpho registry.
You can then set the other Vault's parameters:
- Vault Symbol: Choose a token symbol for your vault.
- Vault Name: Choose a descriptive name for your vault.
- Curator: Assign the curator role for managing vault parameters.
- Allocator: Set the allocator address for managing fund allocations.
- Sentinel (Optional): Optionally assign a sentinel for emergency actions.
- MaxRate: The maximum rate earn by vault's suppliers. MaxRate must be set for suppliers to earn yield (more here).
4. Configure Adapters and Risk Parameters
- Select which Morpho Vault V1 instances you want to use as underlying liquidity markets.
- Set initial risk caps (absolute and relative) for each adapter.
- Configure the liquidity adapter for managing fund flows.
5. Set Timelock (Optional)
Configure timelock durations for critical functions to add an additional security layer for production vaults.
6. Review and Deploy
Review all your configuration settings, then click "Deploy Vault". Your wallet will prompt you to confirm the transaction.
Once deployed, you can continue managing your vault through the Curator App or use the advanced methods described below for programmatic management.
Method 2: Create and Configure a Vault via Script
For developers who prefer a code-based approach, you can use the official Morpho Vaults V2 deployment repository. This method allows you to bundle multiple setup actions into a single, automated script.
Repository: https://github.com/morpho-org/vault-v2-deployment
The Power of Scripted Deployment
The key advantage of using the deployment repository is automation and efficiency. The DeployVaultV2.s.sol script performs the entire initial configuration in one go, leveraging the fact that new vaults have a zero-second timelock by default.
The deployment script performs the following actions:
- Vault Creation: Deploys a new
VaultV2instance using the VaultV2Factory. - Adapter Deployment: Deploys a
MorphoVaultV1Adapterfor the specified Vault V1. - Role Assignment: Configures temporary permissions during deployment, then assigns final
Owner,Curator,Allocator, and optionallySentinelroles. - Core Configuration:
- Submits and executes timelocked configuration changes.
- Enables the adapter on the vault.
- Sets the adapter registry.
- Configures the adapter as the
liquidityAdapter. - Sets initial risk caps (absolute and relative).
- Timelock Hardening: Optionally sets timelocks on critical functions to secure the vault for production use.
- Dead Deposit: Optionally seeds the vault with initial liquidity to prevent inflation attacks.
Prerequisites
Before deploying, ensure you have:
- Foundry installed
- Git installed
- An Ethereum wallet with sufficient funds for deployment
- RPC URL for your target network
Running the Deployment Script
1. Clone the Repository and Install Dependencies
git clone https://github.com/morpho-org/vault-v2-deployment
cd vault-v2-deployment
git submodule update --init --recursive2. Configure Environment Variables
Create a .env file with your deployment configuration:
# Role addresses (replace with your actual addresses)
OWNER=0x... # Final owner of the vault (ideally a multisig)
CURATOR=0x... # Curator address (ideally a multisig)
ALLOCATOR=0x... # Allocator address
SENTINEL=0x... # Sentinel address (optional)
# Timelock duration (in seconds) - set to 0 for immediate execution
TIMELOCK_DURATION=1814400 # 21 days (optional, leave empty for 0)
# Deployed contract addresses (network-specific)
# See https://docs.morpho.org/get-started/resources/addresses/ for addresses
ADAPTER_REGISTRY=0x... # Adapter Registry address
VAULT_V2_FACTORY=0x... # VaultV2 Factory address
MORPHO_VAULT_V1_ADAPTER_FACTORY=0x... # MorphoVaultV1 Adapter Factory address
# Target Vault V1
VAULT_V1=0x... # The Morpho Vault V1 address to use as liquidity market
# RPC and deployment settings
RPC_URL=https://... # Your RPC endpoint
PRIVATE_KEY=0x... # Your private key (keep secure!)
# Optional: For contract verification
ETHERSCAN_API_KEY=... # Your Etherscan API key
DEAD_DEPOSIT_AMOUNT=... # Optional initial deposit to prevent inflation attacksSecurity Note: Never commit your .env file to version control. It contains sensitive information like private keys.
3. Deploy the Vault
Run the deployment script:
# Without block explorer verification
forge script script/DeployVaultV2.s.sol \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--broadcastOr with verification on Etherscan:
# With verification on Etherscan
forge script script/DeployVaultV2.s.sol \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--etherscan-api-key $ETHERSCAN_API_KEY \
--verifyThe script will output the addresses of all deployed contracts and confirm each configuration step.
Testing Before Mainnet Deployment
The repository includes testing tools to help you validate your deployment:
# Run all tests
forge test
# Test deployment on local Anvil network
./deploy_anvil.shImportant: Always test your deployment configuration on a testnet before deploying to mainnet.
Understanding the Deployment Steps
The DeployVaultV2.s.sol script orchestrates a comprehensive deployment process. Here's what happens internally:
Phase 1: Deploy VaultV2 Instance
// Deploy VaultV2 using the factory for deterministic addresses
bytes32 uniqueSalt = keccak256(abi.encodePacked(block.timestamp + gasleft()));
VaultV2 deployedVaultV2 = VaultV2(
VaultV2Factory(factoryAddress).createVaultV2(
temporaryOwner,
underlyingAsset,
uniqueSalt
)
);Phase 2: Configure Temporary Permissions
// Set broadcaster as temporary curator for configuration
vault.setCurator(temporaryCurator);Phase 3: Deploy and Configure Morpho Adapter
// Deploy MorphoVaultV1Adapter using the adapter factory
address morphoAdapter = MorphoVaultV1AdapterFactory(factoryAddress)
.createMorphoVaultV1Adapter(vaultV2Address, vaultV1Address);Phase 4: Submit Timelocked Configuration Changes
// Submit all configuration changes that will be timelocked
vault.submit(abi.encodeCall(vault.setIsAllocator, (allocator, true)));
vault.submit(abi.encodeCall(vault.setAdapterRegistry, (registry)));
vault.submit(abi.encodeCall(vault.setLiquidityAdapterAndData, (adapter, bytes(""))));
bytes memory adapterIdData = abi.encode("this", adapter);
vault.submit(abi.encodeCall(vault.addAdapter, (adapter)));
vault.submit(abi.encodeCall(vault.increaseAbsoluteCap, (adapterIdData, type(uint128).max)));
vault.submit(abi.encodeCall(vault.increaseRelativeCap, (adapterIdData, 1e18)));Phase 5: Execute Immediate Configuration Changes
// Since timelock is 0 initially, execute configurations immediately
vault.setAdapterRegistry(registry);
vault.setIsAllocator(allocator, true);
vault.addAdapter(adapter);
vault.setLiquidityAdapterAndData(adapter, bytes(""));
bytes memory adapterIdData = abi.encode("this", adapter);
vault.increaseAbsoluteCap(adapterIdData, type(uint128).max);
vault.increaseRelativeCap(adapterIdData, 1e18);
// Abdicate setAdapterRegistry function to prevent future changes
vault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setAdapterRegistry.selector)));
vault.abdicate(IVaultV2.setAdapterRegistry.selector);Phase 6: Configure Timelock Settings (Optional)
// Define critical functions that should be timelocked
bytes4[] memory timelockedSelectors = new bytes4[](10);
timelockedSelectors[0] = IVaultV2.setReceiveSharesGate.selector;
timelockedSelectors[1] = IVaultV2.setSendSharesGate.selector;
timelockedSelectors[2] = IVaultV2.setReceiveAssetsGate.selector;
// ... more critical functions
// Submit and execute timelock increases
for (uint256 i = 0; i < timelockedSelectors.length; i++) {
vault.submit(abi.encodeCall(vault.increaseTimelock, (timelockedSelectors[i], timelockDuration)));
vault.increaseTimelock(timelockedSelectors[i], timelockDuration);
}Phase 7: Set Final Role Assignments
// Assign final roles to production addresses
vault.setCurator(vaultCurator);
if (vaultSentinel != address(0)) {
vault.setIsSentinel(vaultSentinel, true);
}
vault.setOwner(vaultOwner);Phase 8: Execute Dead Deposit (Optional)
// Seed vault with initial liquidity to prevent inflation attacks
if (depositAmount > 0) {
IERC20(vault.asset()).approve(address(vault), depositAmount);
vault.deposit(depositAmount, address(0xdead)); // Burned shares
}For a detailed explanation of how to build your own deployment script, see the repository documentation.
Method 3: Create a Vault Manually via Etherscan
If you prefer a manual approach without using the Curator App or deployment scripts, you can deploy a vault directly by interacting with the contracts on a block explorer like Etherscan.
Prerequisites
- An Ethereum wallet (e.g., MetaMask) connected to the desired network.
- The address of the ERC-20 token the vault will use as its
asset. - The address you want to designate as the initial
owner.
Step-by-Step Guide
1. Deploy a New VaultV2 Contract
Since Vault V2 doesn't use a factory pattern, you'll need to deploy the contract directly. This typically requires using a development environment like Remix or Foundry.
For Remix:
- Copy the
VaultV2.solcontract and its dependencies. - Compile with Solidity 0.8.28.
- Deploy with constructor parameters:
_owner: The initial owner address (ideally your multisig)._asset: The ERC-20 token address (e.g., USDC, WETH).
2. Verify the Contract
After deployment, verify the contract on Etherscan to enable the Write Contract interface.
3. Configure the Vault
Once deployed and verified, you'll need to:
- Set up roles (see Manage Vault V2 Roles).
- Deploy and configure adapters (see (De)List Adapters).
Congratulations! Your vault is now deployed. For a production-ready setup, we strongly recommend using the deployment script method as it ensures all components are properly configured.
