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:

ContractPurposeKey Benefit
VaultRouterBundled UX with auto-claimSingle-transaction experience
AutoClaimKeeperKeeper auto-claim serviceHands-free claim execution
InstantLiquidityPoolInstant liquidity AMMSkip 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 address
  • assets: Amount of underlying tokens to deposit
  • minShares: Minimum shares to receive (slippage protection)
  • receiver: Address to receive the vault shares
  • autoClaim: Enable automatic claim when fulfilled (0.1% fee)

Example:

// Deposit 1000 tUSDC 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

ServiceFeeDescription
Standard Request0%No fee for manual claim
Auto-Claim0.1%Deducted from claimed amount
Gasless2%+Covers gas + relayer profit

Configuration

ParameterDefaultDescription
defaultTimeout1 hourRequest expiration time
autoClaimFeeBps10 (0.1%)Fee for auto-claim service

AutoClaimKeeper

The AutoClaimKeeper enables keeper nodes to earn rewards by executing auto-claims for users. It integrates with TrustFingerprint for reputation-based reward scaling.

Key Features

  • Keeper 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(uint256 stake) external payable;

Requirements:

  • Minimum TrustFingerprint: 0.70 (MIN_TRUST_SCORE = 700 in contract)
  • Stake: any amount sent as msg.value (no enforced minimum)

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 tUSDC
  • Base reward rate: 0.1%
  • TrustFingerprint: 0.85
  • Trust bonus rate: 0.05%
Base Reward = 10,000 × 0.001 = 10 tUSDC
Trust Bonus = 10 × 0.85 × 0.0005 = 0.00425 tUSDC
Total Reward = 10.00425 tUSDC

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

ConditionPenalty
Failed execution0.1% of stake
>10% failure rateTemporary suspension
Malicious behaviorFull 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: tUSDC (the vault underlying asset) 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

The fee is calculated using a linear formula based on pool utilization:

feeBps = MIN_FEE_BPS + ((MAX_FEE_BPS - MIN_FEE_BPS) × utilization) / 10000
= 200 + (300 × utilization / 10000)
UtilizationFee (approx.)
0%2.0%
25%2.75%
50%3.5%
75%4.25%
100%5.0%

Fee scales continuously and linearly, not in discrete steps.

Fee Distribution:

  • 90% to LPs (proportional to stake)
  • 10% to protocol treasury

LP Economics

Important: Returns to instant-liquidity LPs are fee income driven entirely by instant-flow volume, fee tier, pool size, and competition among LPs. They are not a protocol yield and are separate from Noderr's canonical yield model (vault depositors target ~10% blended; the combined vault + node target is 8-28%). The figures below are illustrative of the fee-share mechanic only and are not projected, expected, or guaranteed returns.

Illustrative mechanic (not a yield projection):

  • LP provides 10,000 tUSDC liquidity
  • Suppose the pool processes 50,000 tUSDC/day of instant flow at a 3% average fee
  • Gross daily fees: 1,500 tUSDC (3% of 50,000)
  • LP share at 90% fee distribution, holding 10% of the pool: 135 tUSDC/day

Realized returns depend on actual instant-flow volume, the prevailing utilization-based fee, the LP's share of the pool, and competition. Sustained high volume at these assumptions would be exceptional; in practice instant-flow demand is variable and may be low, so LPs should not assume the illustrative throughput above.


Integration Guide

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

ContractAddressNetwork
VaultRouterPending DeploymentBase Sepolia
AutoClaimKeeperPending DeploymentBase Sepolia
InstantLiquidityPoolPending DeploymentBase Sepolia

Security Considerations

Access Control

ContractRolePermissions
VaultRouterOPERATOR_ROLEExecute auto-claims
VaultRouterPAUSER_ROLEEmergency pause
AutoClaimKeeperKEEPER_ROLEExecute claims
InstantLiquidityPoolREBALANCER_ROLETrigger rebalancing

Emergency Functions

All contracts implement:

  • pause() / unpause() - Halt operations
  • emergencyWithdraw() - 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.



Last Updated: December 28, 2025

Version: 1.0

results matching ""

    No results matching ""