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 Morpho Vault V2 via Script
For developers who prefer a code-based approach, you can refer to the Morpho Vault V2 deployment repository. This repository contains an example script that bundles multiple setup actions into a single transaction.
Repository: https://github.com/morpho-org/vault-v2-deployment
Overview
The DeployVaultV2WithMarketAdapter.s.sol script demonstrates how to deploy and configure a Morpho Vault V2. It leverages the fact that new vaults have a zero-second timelock by default, allowing all initial configuration to be executed immediately.
This script deploys a Morpho Vault V2 using MorphoMarketV1AdapterV2, which connects directly to Morpho Markets V1.
The deployment process consists of the following phases:
| Phase | Description |
|---|---|
| 1 | Deploy Morpho Vault V2 instance via factory |
| 2 | Configure temporary permissions |
| 3 | Deploy MorphoMarketV1AdapterV2 |
| 4 | Submit timelocked configuration changes |
| 5 | Execute configuration + gates abdication |
| 6 | Set final role assignments |
| 7 | Configure market and liquidity adapter |
| 8 | Execute vault dead deposit |
| 9 | Configure vault timelocks |
| 10 | Configure adapter timelocks |
Prerequisites
Before deploying, ensure you have:
- Foundry installed
- Git installed
- An Ethereum wallet with sufficient funds for deployment
- RPC URL for your target network
- Sufficient tokens for the dead deposit (required for inflation attack protection)
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
forge install2. Configure Environment Variables
Create a .env file with your deployment configuration:
# Network
RPC_URL=https://... # Your RPC endpoint
PRIVATE_KEY=0x... # Your private key (keep secure!)
# Role addresses (replace with your actual addresses)
OWNER=0x... # Final owner of the vault (ideally a multisig)
CURATOR=0x... # Curator address (defaults to OWNER if not set)
ALLOCATOR=0x... # Allocator address (defaults to OWNER if not set)
SENTINEL=0x... # Sentinel address (optional)
# Deployed contract addresses (network-specific)
# See https://docs.morpho.org/get-started/resources/addresses/ for addresses
ASSET=0x... # Underlying asset token (e.g., USDC, WETH)
ADAPTER_REGISTRY=0x... # Morpho Registry address
VAULT_V2_FACTORY=0x... # VaultV2 Factory address
MORPHO_MARKET_V1_ADAPTER_V2_FACTORY=0x... # MorphoMarketV1AdapterV2 Factory address
# First market configuration (optional - set to 0x0 to skip)
MARKET_ID=0x... # Morpho Blue market ID
COLLATERAL_TOKEN_CAP=... # Max allocation to collateral token
MARKET_CAP=... # Max allocation to specific market
# Timelock configuration (in seconds)
# Good practice is a minimum 3 days = 259200 seconds
VAULT_TIMELOCK_DURATION=259200
ADAPTER_TIMELOCK_DURATION=259200
# Optional: For contract verification
ETHERSCAN_API_KEY=... # Your Etherscan API key3. Simulate the Deployment
First, simulate the deployment to verify everything works:
source .env && forge script script/DeployVaultV2WithMarketAdapter.s.sol \
--fork-url "$RPC_URL" \
--private-key "$PRIVATE_KEY" \
-vvvIn simulation mode (without --broadcast), the script will complete all deployment phases and gracefully skip the dead deposit if the deployer has no tokens.
4. Deploy the Morpho Vault V2
Run the deployment script with --broadcast to execute on-chain:
# Without block explorer verification
forge script script/DeployVaultV2WithMarketAdapter.s.sol \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--broadcastOr with verification on Etherscan:
# With verification on Etherscan
forge script script/DeployVaultV2WithMarketAdapter.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 on fork
source .env && forge test --fork-url "$RPC_URL" -vvv
# Run specific test
forge test --match-test test_FullDeploymentWithTimelocks -vvvImportant: Always test your deployment configuration on a testnet before deploying to mainnet.
Good practices
The script addresses the following good practices:
| Good practices | How Script Addresses It |
|---|---|
| Non-custodial Gates | Phase 5: Gates abdicated (cannot be re-enabled) |
| No Idle Liquidity | Phase 7: liquidityAdapter allocates deposits to market |
| Dead Deposit | Phase 8: 1e9-1e12 wei deposited on behalf of 0xdead |
| Vault Timelocks | Phase 9: Configures timelocks for vault functions (>= 3 days) |
| Adapter Timelocks | Phase 10: Configures adapter timelocks (burnShares >= 3 days) |
| Naming Restriction | Manual check: Name/symbol cannot contain "morpho" |
Understanding the Deployment Steps
The DeployVaultV2WithMarketAdapter.s.sol script orchestrates a comprehensive deployment process. Here's what happens internally:
Phase 1: Deploy Morpho Vault V2 Instance
// Deploy Morpho Vault V2 using the factory
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 MorphoMarketV1AdapterV2
// Deploy MorphoMarketV1AdapterV2 using the adapter factory
IMorphoMarketV1AdapterV2Factory factory = IMorphoMarketV1AdapterV2Factory(factoryAddress);
address adapterAddress = factory.createMorphoMarketV1AdapterV2(vaultV2Address);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)));
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)));
// Submit abdication for registry and gates (non-custodial requirement)
vault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setAdapterRegistry.selector)));
vault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setReceiveSharesGate.selector)));
vault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setSendSharesGate.selector)));
vault.submit(abi.encodeCall(vault.abdicate, (IVaultV2.setReceiveAssetsGate.selector)));Phase 5: Execute Configuration and Gates Abdication
// Since timelock is 0 initially, execute configurations immediately
vault.setAdapterRegistry(registry);
vault.setIsAllocator(allocator, true);
vault.addAdapter(adapter);
bytes memory adapterIdData = abi.encode("this", adapter);
vault.increaseAbsoluteCap(adapterIdData, type(uint128).max);
vault.increaseRelativeCap(adapterIdData, 1e18);
// Abdicate registry and gates (preserves non-custodial properties)
vault.abdicate(IVaultV2.setAdapterRegistry.selector);
vault.abdicate(IVaultV2.setReceiveSharesGate.selector);
vault.abdicate(IVaultV2.setSendSharesGate.selector);
vault.abdicate(IVaultV2.setReceiveAssetsGate.selector);Phase 6: 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 7: Configure Market and Liquidity Adapter
// Look up MarketParams from Morpho and set liquidity adapter
MarketParams memory marketParams = IMorpho(morpho).idToMarketParams(Id.wrap(marketId));
bytes memory liquidityData = abi.encode(marketParams);
vault.setLiquidityAdapterAndData(address(adapter), liquidityData);
// Configure collateral token and market caps
bytes memory collateralTokenIdData = abi.encode("collateralToken", marketParams.collateralToken);
vault.increaseAbsoluteCap(collateralTokenIdData, collateralTokenCap);
vault.increaseRelativeCap(collateralTokenIdData, 1e18);
bytes memory marketIdData = abi.encode("this/marketParams", address(adapter), marketParams);
vault.increaseAbsoluteCap(marketIdData, marketCap);
vault.increaseRelativeCap(marketIdData, 1e18);Phase 8: Execute Dead Deposit
// Seed vault with initial liquidity to prevent inflation attacks
// Amount depends on asset decimals: 1e9 for >= 10 decimals, 1e12 for <= 9 decimals
IERC20(vault.asset()).approve(address(vault), depositAmount);
vault.deposit(depositAmount, address(0xdead)); // Burned sharesPhase 9: Configure Vault Timelocks
// Configure timelocks for vault functions (good practices: >= 3 days)
bytes4[] memory selectors = new bytes4[](7);
selectors[0] = IVaultV2.addAdapter.selector;
selectors[1] = IVaultV2.increaseAbsoluteCap.selector;
selectors[2] = IVaultV2.increaseRelativeCap.selector;
selectors[3] = IVaultV2.setForceDeallocatePenalty.selector;
selectors[4] = IVaultV2.abdicate.selector;
selectors[5] = IVaultV2.removeAdapter.selector;
selectors[6] = IVaultV2.increaseTimelock.selector; // MUST BE LAST!
for (uint256 i = 0; i < selectors.length; i++) {
vault.submit(abi.encodeCall(vault.increaseTimelock, (selectors[i], timelockDuration)));
vault.increaseTimelock(selectors[i], timelockDuration);
}Phase 10: Configure Adapter Timelocks
// Configure timelocks for adapter functions (good practices: burnShares >= 3 days)
bytes4[] memory selectors = new bytes4[](4);
selectors[0] = IMorphoMarketV1AdapterV2.abdicate.selector;
selectors[1] = IMorphoMarketV1AdapterV2.setSkimRecipient.selector;
selectors[2] = IMorphoMarketV1AdapterV2.burnShares.selector;
selectors[3] = IMorphoMarketV1AdapterV2.increaseTimelock.selector; // MUST BE LAST!
for (uint256 i = 0; i < selectors.length; i++) {
adapter.submit(abi.encodeCall(adapter.increaseTimelock, (selectors[i], timelockDuration)));
adapter.increaseTimelock(selectors[i], timelockDuration);
}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.
