Vault UX Improvements
This document provides comprehensive technical documentation for Noderr Protocol's institutional-grade ERC-7540 UX improvement contracts.
Overview
While ERC-7540 provides powerful async vault capabilities, the 2-step flow creates UX friction for users. Noderr Protocol has developed three complementary contracts that transform these "downsides" into competitive advantages:
| Contract | Purpose | Key Benefit |
|---|---|---|
| VaultRouter | Bundled UX with auto-claim | Single-transaction experience |
| AutoClaimKeeper | Validator auto-claim service | Hands-free claim execution |
| InstantLiquidityPool | Instant liquidity AMM | Skip the wait entirely |
VaultRouter
The VaultRouter is the primary interface for users interacting with ERC-7540 vaults. It provides a single-transaction UX by handling request submission, fulfillment monitoring, and claim execution.
Key Features
- Single-Transaction UX: Users interact once; router handles the rest
- Auto-Claim Service: Automatic claim execution when requests are fulfilled
- Batch Operations: Deposit/redeem across multiple vaults in one transaction
- Gasless Transactions: EIP-712 signatures for gas-free operations
- Slippage Protection: Configurable minimum output guarantees
- Emergency Controls: Pause functionality for security incidents
Architecture
User → VaultRouter → ERC-7540 Vault
↓
AutoClaimKeeper
↓
Automatic Claim
Core Functions
Request Deposit with Auto-Claim
function requestDeposit(
address vault,
uint256 assets,
uint256 minShares,
address receiver,
bool autoClaim
) external returns (uint256 requestId);
Parameters:
vault: The ERC-7540 vault addressassets: Amount of underlying tokens to depositminShares: Minimum shares to receive (slippage protection)receiver: Address to receive the vault sharesautoClaim: Enable automatic claim when fulfilled (0.1% fee)
Example:
// Deposit 1000 NODR with auto-claim enabledawait vaultRouter.requestDeposit(
conservativeVaultAddress,
parseUnits('1000', 18),
parseUnits('990', 18), // Accept up to 1% slippage
userAddress,
true// Enable auto-claim
);
Batch Deposit
function batchDeposit(
BatchDepositParams[] calldata params,
address receiver,
bool autoClaim
) external;
struct BatchDepositParams {
address vault;
uint256 assets;
uint256 minShares;
}
Deposit to multiple vaults in a single transaction, saving 50-70% on gas costs.
Example:
// Deposit to 3 vaults at onceawait vaultRouter.batchDeposit([
{ vault: conservativeVault, assets: parseUnits('500', 18), minShares: parseUnits('495', 18) },
{ vault: moderateVault, assets: parseUnits('300', 18), minShares: parseUnits('297', 18) },
{ vault: aggressiveVault, assets: parseUnits('200', 18), minShares: parseUnits('196', 18) }
], userAddress, true);
Gasless Deposit (EIP-712)
function depositWithPermit(
address vault,
uint256 assets,
uint256 minShares,
address receiver,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 requestId);
Users sign a message offchain; relayers submit the transaction and pay gas.
Fee Structure
| Service | Fee | Description |
|---|---|---|
| Standard Request | 0% | No fee for manual claim |
| Auto-Claim | 0.1% | Deducted from claimed amount |
| Gasless | 2%+ | Covers gas + relayer profit |
Configuration
| Parameter | Default | Description |
|---|---|---|
defaultTimeout | 1 hour | Request expiration time |
autoClaimFeeBps | 10 (0.1%) | Fee for auto-claim service |
AutoClaimKeeper
The AutoClaimKeeper enables validator nodes to earn rewards by executing auto-claims for users. It integrates with TrustFingerprint™ for reputation-based reward scaling.
Key Features
- Validator Registration: Stake NODR to become a keeper
- TrustFingerprint™ Integration: Higher trust = higher rewards
- Batch Execution: Process multiple claims efficiently
- Performance Tracking: Success rate, gas usage, rewards
- Slashing Mechanism: Penalties for failed executions
Becoming a Keeper
function registerKeeper() external;
Requirements:
- Minimum stake: 1,000 NODR
- Minimum TrustFingerprint™: 0.50
Executing Claims
// Execute single deposit claim
function executeDepositClaim(
address user,
address vault,
address receiver
) external;
// Execute single redeem claim
function executeRedeemClaim(
address user,
address vault,
address receiver
) external;
// Batch execute multiple claims
function batchExecuteClaims(
ClaimParams[] calldata deposits,
ClaimParams[] calldata redeems
) external;
Reward Calculation
Base Reward = claimValue × baseRewardBps / 10000
Trust Bonus = Base Reward × (trustScore / 100) × trustBonusBps / 10000
Total Reward = Base Reward + Trust Bonus
Example:
- Claim value: 10,000 NODR
- Base reward rate: 0.1%
- TrustFingerprint™: 0.85
- Trust bonus rate: 0.05%
Base Reward = 10,000 × 0.001 = 10 NODR
Trust Bonus = 10 × 0.85 × 0.0005 = 0.00425 NODR
Total Reward = 10.00425 NODR
Keeper Metrics
struct KeeperMetrics {
uint256 totalClaims; // Total claims executed
uint256 successfulClaims; // Successful executions
uint256 failedClaims; // Failed executions
uint256 totalGasUsed; // Cumulative gas usage
uint256 totalRewards; // Cumulative rewards earned
uint256 lastClaimTime; // Timestamp of last claim
}
Slashing Conditions
| Condition | Penalty |
|---|---|
| Failed execution | 0.1% of stake |
| >10% failure rate | Temporary suspension |
| Malicious behavior | Full stake slash |
InstantLiquidityPool
The InstantLiquidityPool provides immediate deposit/withdrawal execution for users who prefer speed over cost. LPs earn fees from impatient users.
Key Features
- Instant Deposits: Skip the 1-2 hour wait
- Instant Redemptions: Immediate asset return
- Dynamic Pricing: 2-5% fee based on utilization
- LP Rewards: Earn fees by providing liquidity
- Automated Rebalancing: Pool maintains optimal levels
How It Works
Standard Flow (1-2 hours):
User → requestDeposit → [wait] → claimDeposit → Shares
Instant Flow (immediate):
User → instantDeposit → Shares (pay 2-5% premium)
For Users: Instant Operations
Instant Deposit
function instantDeposit(
address vault,
uint256 assets,
uint256 minShares,
address receiver
) external returns (uint256 shares);
Example:
// Instant deposit with 3% feeconst shares = await instantLiquidityPool.instantDeposit(
conservativeVaultAddress,
parseUnits('1000', 18),
parseUnits('950', 18), // Accept up to 5% slippage (includes fee)
userAddress
);
Instant Redeem
function instantRedeem(
address vault,
uint256 shares,
uint256 minAssets,
address receiver
) external returns (uint256 assets);
For LPs: Providing Liquidity
Add Liquidity
function addLiquidity(
address vault,
uint256 assets,
uint256 shares
) external;
LPs can provide:
- Asset liquidity: NODR tokens for instant deposits
- Share liquidity: Vault shares for instant redemptions
Remove Liquidity
function removeLiquidity(
address vault,
uint256 assets,
uint256 shares
) external;
Claim Fees
function claimFees(address vault) external;
Fee Structure
| Utilization | Fee |
|---|---|
| 0-20% | 2.0% |
| 20-40% | 2.5% |
| 40-60% | 3.0% |
| 60-80% | 3.5% |
| 80-100% | 5.0% |
Fee Distribution:
- 90% to LPs (proportional to stake)
- 10% to protocol treasury
LP Economics
Expected Returns:
- Low utilization: 20-50% APY
- Medium utilization: 50-100% APY
- High utilization: 100-150% APY
Example:
- LP provides 10,000 NODR liquidity
- Pool processes 100,000 NODR/day at 3% average fee
- Daily fees: 3,000 NODR
- LP share (10% of pool): 300 NODR/day
- Annual return: 300 × 365 = 109,500 NODR (1,095% APY)
Note: Returns vary based on utilization and competition.
Integration Guide
Recommended User Flow
1. Check instant liquidity availability
2. If available and user prefers speed → Use InstantLiquidityPool
3. If user prefers cost savings → Use VaultRouter with auto-claim
4. If user wants full control → Use VaultRouter without auto-claim
TypeScript Integration
import { parseUnits } from'viem';
// Option 1: Instant deposit (immediate, 2-5% fee)const instantShares = await instantLiquidityPool.instantDeposit(
vaultAddress,
parseUnits('1000', 18),
parseUnits('950', 18),
userAddress
);
// Option 2: Auto-claim deposit (1-2 hours, 0.1% fee)await vaultRouter.requestDeposit(
vaultAddress,
parseUnits('1000', 18),
parseUnits('990', 18),
userAddress,
true// auto-claim
);
// Option 3: Manual deposit (1-2 hours, 0% fee)await vaultRouter.requestDeposit(
vaultAddress,
parseUnits('1000', 18),
parseUnits('990', 18),
userAddress,
false// manual claim
);
// Later: manually claimconst shares = await vaultRouter.claimDeposit(vaultAddress, userAddress);
Solidity Integration
import "./interfaces/IVaultRouter.sol";
import "./interfaces/IInstantLiquidityPool.sol";
contract MyProtocol {
IVaultRouter public vaultRouter;
IInstantLiquidityPool public instantPool;
function smartDeposit(
address vault,
uint256 amount,
bool preferSpeed
) external {
if (preferSpeed && instantPool.hasLiquidity(vault, amount)) {
// Instant deposit
instantPool.instantDeposit(vault, amount, 0, msg.sender);
} else {
// Auto-claim deposit
vaultRouter.requestDeposit(vault, amount, 0, msg.sender, true);
}
}
}
Deployed Contracts
| Contract | Address | Network |
|---|---|---|
| VaultRouter | Pending Deployment | Base Sepolia |
| AutoClaimKeeper | Pending Deployment | Base Sepolia |
| InstantLiquidityPool | Pending Deployment | Base Sepolia |
Security Considerations
Access Control
| Contract | Role | Permissions |
|---|---|---|
| VaultRouter | OPERATOR_ROLE | Execute auto-claims |
| VaultRouter | PAUSER_ROLE | Emergency pause |
| AutoClaimKeeper | KEEPER_ROLE | Execute claims |
| InstantLiquidityPool | REBALANCER_ROLE | Trigger rebalancing |
Emergency Functions
All contracts implement:
pause()/unpause()- Halt operationsemergencyWithdraw()- Admin asset recovery- UUPS upgradeable pattern for security patches
Audit Status
These contracts are pending third-party security audit. Use on testnet only until audits are complete.
Related Documentation
- Vault Contracts - ERC-7540 vault documentation
- Contract Addresses - Deployed contract addresses
- Node Operators Guide - Running keeper nodes
- Deposit Guide - User deposit guide
Last Updated: December 28, 2025
Version: 1.0