Skip to main content

Cluster Deployment & Management using scripts

The euler-vault-scripts repository provides a robust, script-based framework for deploying, configuring, and managing clusters of EVK vaults. It is the recommended tool for advanced users, DAOs, and protocol developers who need automation and support for complex, governed markets.

What is a Cluster?

A cluster is a collection of vaults that accept each other as collateral and share a common governor. Clusters are defined and managed in Solidity scripts, enabling programmable, auditable, and reproducible market deployments.

Key Features

  • Automated deployment and delta management
  • Support for Safe multisigs, timelocks, and risk stewards
  • Batching, emergency operations, and governance contract integration

Defining a Cluster: Example

Below are annotated snippets from a typical cluster script (Cluster.s.sol).

1. Define Cluster Assets

function defineCluster() internal override {
// List the assets for which vaults will be deployed
cluster.assets = [WETH, USDC, USDT, sUSDS];
}

This sets up the vaults in your cluster. Each asset will have its own vault. Do not define more than one vault per asset.

2. Configure Cluster Parameters

function configureCluster() internal override {
// Set the governor addresses for vaults and oracle routers
cluster.oracleRoutersGovernor = getDeployer();
cluster.vaultsGovernor = getDeployer();

// Set the unit of account (e.g., USD)
cluster.unitOfAccount = USD;

// Set protocol-wide parameters
cluster.feeReceiver = address(0);
cluster.interestFee = 0.1e4; // 1%
cluster.maxLiquidationDiscount = 0.15e4; // 1.5%
cluster.liquidationCoolOffTime = 1; // seconds

// Set hooks, config flags, etc. as needed
cluster.hookTarget = address(0);
cluster.hookedOps = 0;
cluster.configFlags = 0;
}

This block configures governance, risk, and operational parameters for the cluster. You can override parameters per asset if needed.

3. Set Oracle Providers

// Assign oracle adapters or external vaults for each asset
cluster.oracleProviders[WETH ] = "0x10674C8C1aE2072d4a75FE83f1E159425fd84E1D";
cluster.oracleProviders[USDC ] = "0x6213f24332D35519039f2afa7e3BffE105a37d3F";
cluster.oracleProviders[USDT ] = "0x587CABe0521f5065b561A6e68c25f338eD037FF9";
cluster.oracleProviders[sUSDS] = "ExternalVault|0xD0dAb9eDb2b1909802B03090eFBF14743E7Ff967";

Each asset must have a price source. For underlying assets being ERC-4626 vaults, use the ExternalVault| prefix to resolve via convertToAssets.

Before configuring oracle providers, check the Euler Oracles Dashboard to see if there are existing oracles that meet your needs. The dashboard provides a comprehensive overview of all available oracles, their configurations, and their current status. Using an existing oracle can save time and reduce deployment complexity.

4. Set Supply and Borrow Caps

cluster.supplyCaps[WETH ] = 10_000;
cluster.supplyCaps[USDC ] = 10_000_000;
cluster.supplyCaps[USDT ] = 10_000_000;
cluster.supplyCaps[sUSDS] = 10_000_000;

cluster.borrowCaps[WETH ] = 9_000;
cluster.borrowCaps[USDC ] = 9_000_000;
cluster.borrowCaps[USDT ] = 9_000_000;
cluster.borrowCaps[sUSDS] = type(uint256).max; // no cap

Caps control the maximum supply and borrowable amounts for each vault.

5. Assign Interest Rate Models (IRMs)

uint256[4] memory irmETH = [uint256(0), uint256(194425692), uint256(41617711740), uint256(3865470566)];
uint256[4] memory irmUSD = [uint256(0), uint256(399976852), uint256(39767751304), uint256(3865470566)];

cluster.kinkIRMParams[WETH ] = irmETH;
cluster.kinkIRMParams[USDC ] = irmUSD;
cluster.kinkIRMParams[USDT ] = irmUSD;

Interest rate models are set per asset. Use the provided scripts/utilities or Creator UI to generate IRM parameters as needed.

6. Configure LTVs and Liquidation Parameters

// Liquidation LTV matrix: columns = liability vaults, rows = collateral vaults
cluster.ltvs = [
// WETH USDC USDT sUSDS
[uint16(0.00e4), 0.85e4, 0.85e4, 0.00e4], // WETH
[uint16(0.87e4), 0.00e4, 0.95e4, 0.00e4], // USDC
[uint16(0.87e4), 0.95e4, 0.00e4, 0.00e4], // USDT
[uint16(0.87e4), 0.95e4, 0.95e4, 0.00e4] // sUSDS
];

7. Configure Spread LTV

// Set the spread LTV for the entire cluster
cluster.spreadLTV = 0.02e4; // 2% spread

The spread LTV represents the difference between the liquidation threshold and the maximum LTV for all assets in the cluster. This creates a buffer zone before liquidation can occur, providing protection against immediate liquidations when positions approach their maximum LTV.

Environment Setup and Running Scripts

Prerequisites

  1. Install Foundry:
curl -L https://foundry.paradigm.xyz | bash
foundryup
  1. Clone the repository:
git clone https://github.com/euler-xyz/euler-vault-scripts.git
cd euler-vault-scripts
  1. Prepare the .env file using .env.example as a template. Define the RPC URLs for all the chain IDs you need.

  2. Install dependencies:

./install.sh
  1. Compile the contracts:
forge clean && forge compile

Running Scripts

Use the ExecuteSolidityScript.sh script to run the management script:

./script/ExecuteSolidityScript.sh script/clusters/[CLUSTER_FILE] [options]

Replace [CLUSTER_FILE] with your cluster-specific file name (e.g., Cluster.s.sol).

Important Options:

  • --dry-run: Simulates the script without executing transactions
  • --rpc-url URL|CHAIN_ID: Required if DEPLOYMENT_RPC_URL not defined in .env
  • --account ACCOUNT or --ledger: Required if DEPLOYER_KEY not defined in .env
  • --batch-via-safe: Creates a batch payload file for Safe multisig execution
  • --safe-address SAFE_ADDRESS: Authorized Safe multisig address
  • --timelock-address: Schedules transactions in the timelock controller
  • --risk-steward-address: Executes transactions via the risk steward contract

Example Commands:

Initial deployment:

./script/ExecuteSolidityScript.sh ./script/clusters/Cluster.s.sol --account DEPLOYER --rpc-url 1

Managing a deployed cluster with governance contracts:

./script/ExecuteSolidityScript.sh ./script/clusters/Cluster.s.sol --batch-via-safe --safe-address DAO --timelock-address wildcard --rpc-url 1

Important Notes

  • Always use --dry-run first to simulate transactions and check for potential issues
  • Environment variables in .env take precedence over command line arguments
  • After deployment, commit the generated .json files in the scripts directory as they serve as the deployed contracts addresses cache

Further Reading & References