The ZEUR vault system automatically stakes deposited collateral across multiple liquid staking token (LST) protocols to maximize yield while maintaining liquidity. This innovative approach allows users to earn staking rewards on their collateral while simultaneously using it for borrowing, significantly improving capital efficiency.
Vault Architecture
VaultETH (Ethereum Vault)
The ETH vault manages Ethereum deposits and distributes them across multiple LST protocols:
contractVaultETHisAccessManagedUpgradeable, UUPSUpgradeable, IVault{// Staking routers for different LST protocolsmapping(address=>bool)public stakingRouters;// Track staked amounts per protocolmapping(address=>uint256)public stakedAmounts;}
Supported LST Protocols:
Lido: stETH integration
RocketPool: rETH integration
EtherFi: eETH integration
Morpho: Morpho vault integration
VaultLINK (Chainlink Vault)
The LINK vault manages LINK token deposits and stakes them via StakeLink:
Supported Staking:
StakeLink: stLINK integration
Staking Router System
Router Architecture
Each LST protocol has a dedicated staking router that handles protocol-specific interactions:
Staking rewards are automatically collected and managed:
Reward Distribution
Options for reward handling:
Auto-Compound: Automatically restake rewards
Protocol Fee: Take percentage for protocol treasury
User Distribution: Distribute proportionally to depositors
Liquidity Management
Withdrawal Queue
For protocols with withdrawal delays:
Liquidity Buffer
Maintain liquid reserves for immediate withdrawals:
Integration Benefits
For Users
Passive Income: Automatic staking rewards
Diversification: Risk spread across multiple protocols
No Management: Set-and-forget staking
Liquidity: Collateral remains borrowable
For Protocol
Yield Generation: Additional revenue streams
Competitive Advantage: Higher effective APY
Risk Mitigation: Protocol diversification
Capital Efficiency: Productive use of idle assets
Risk Management
Protocol Risk Mitigation
Diversification: Multiple LST protocols
Allocation Limits: Maximum exposure per protocol
Emergency Controls: Pause and withdraw mechanisms
Insurance Integration: Slashing protection where available
Slashing Risk Management
Monitoring and Alerts
Gas Optimization
Batch Operations
Efficient Rebalancing
Minimize number of transactions
Optimize gas usage across protocols
Batch reward collection and distribution
The vault system provides a sophisticated foundation for automated yield generation while maintaining the liquidity and composability required for the ZEUR lending protocol.
interface IStakingRouter {
function stake(address from, uint256 amount) external;
function unstake(address to, uint256 amount) external;
function getStakedBalance() external view returns (uint256);
function getUnderlyingBalance() external view returns (uint256);
}
contract StakingRouterETHLido is AccessManagedUpgradeable, UUPSUpgradeable {
ILido public lido;
IERC20 public stETH;
function stake(address from, uint256 amount) external {
// Stake ETH with Lido to receive stETH
uint256 stETHReceived = lido.submit{value: amount}(address(0));
// Track stETH balance
emit Staked(from, amount, stETHReceived);
}
function unstake(address to, uint256 amount) external {
// Request withdrawal from Lido
// Handle stETH -> ETH conversion
lido.requestWithdrawals([amount], [address(this)]);
}
}
contract StakingRouterETHRocketPool is AccessManagedUpgradeable, UUPSUpgradeable {
IRocketDepositPool public rocketDepositPool;
IERC20 public rETH;
function stake(address from, uint256 amount) external {
// Deposit ETH to RocketPool
rocketDepositPool.deposit{value: amount}();
// Receive rETH tokens
uint256 rETHBalance = rETH.balanceOf(address(this));
emit Staked(from, amount, rETHBalance);
}
function unstake(address to, uint256 amount) external {
// Burn rETH for ETH
IRocketTokenRETH(address(rETH)).burn(amount);
// Transfer ETH to user
payable(to).transfer(amount);
}
}
contract StakingRouterETHEtherfi is AccessManagedUpgradeable, UUPSUpgradeable {
IEtherFi public etherFi;
IERC20 public eETH;
function stake(address from, uint256 amount) external {
// Deposit ETH to EtherFi
uint256 eETHReceived = etherFi.depositToEtherFiNode{value: amount}();
emit Staked(from, amount, eETHReceived);
}
function unstake(address to, uint256 amount) external {
// Request withdrawal from EtherFi
etherFi.requestWithdraw(address(this), amount);
}
}
contract StakingRouterETHMorpho is AccessManagedUpgradeable, UUPSUpgradeable {
IMorphoVault public morphoVault;
function stake(address from, uint256 amount) external {
// Deposit ETH to Morpho vault
uint256 shares = morphoVault.deposit{value: amount}(amount, address(this));
emit Staked(from, amount, shares);
}
function unstake(address to, uint256 amount) external {
// Withdraw from Morpho vault
morphoVault.withdraw(amount, to, address(this));
}
}
contract StakingRouterLINK is AccessManagedUpgradeable, UUPSUpgradeable {
IStakeLink public stakeLink;
IERC20 public linkToken;
IERC20 public stLINK;
function stake(address from, uint256 amount) external {
// Approve LINK to StakeLink
linkToken.approve(address(stakeLink), amount);
// Stake LINK for stLINK
stakeLink.stake(amount, false, new bytes[](0));
uint256 stLINKReceived = stLINK.balanceOf(address(this));
emit Staked(from, amount, stLINKReceived);
}
function unstake(address to, uint256 amount) external {
// Unstake stLINK for LINK
stakeLink.unstake(amount, 0, new bytes32[](0), false, false, new bytes[](0));
// Transfer LINK to user
linkToken.transfer(to, amount);
}
}
struct AllocationStrategy {
uint256 lidoTarget; // 40% to Lido
uint256 rocketTarget; // 30% to RocketPool
uint256 etherfiTarget; // 20% to EtherFi
uint256 morphoTarget; // 10% to Morpho
}
function rebalance() external {
// Calculate current allocations
uint256 totalStaked = getTotalStaked();
// Calculate target allocations
AllocationStrategy memory targets = getAllocationTargets();
// Rebalance if deviation > threshold
if (needsRebalancing(targets)) {
executeRebalancing(targets);
}
}
function lockCollateral(address from, uint256 amount) external payable {
require(msg.sender == poolAddress, "Only pool can lock");
if (address(this) == vaultETH) {
// Distribute ETH across staking routers
distributeToStakingRouters(amount);
} else {
// Handle LINK staking
stakeLINK(amount);
}
emit CollateralLocked(from, amount);
}
function unlockCollateral(address to, uint256 amount) external {
require(msg.sender == poolAddress, "Only pool can unlock");
// Unstake from protocols to fulfill withdrawal
unstakeFromProtocols(amount);
// Transfer unstaked assets to user
transferToUser(to, amount);
emit CollateralUnlocked(to, amount);
}
function emergencyUnstake(uint256 amount) external restricted {
// Unstake from most liquid protocols first
unstakeUrgent(amount);
}
function collectRewards() external {
uint256 totalRewards = 0;
// Collect from all staking routers
for (uint i = 0; i < stakingRouters.length; i++) {
uint256 rewards = stakingRouters[i].collectRewards();
totalRewards += rewards;
}
// Distribute rewards (compound or distribute)
distributeRewards(totalRewards);
}