๐Ÿ› ๏ธ Behind the Scenes: How to Deploy a $XXM Private Credit Facility (Technical Deep-Dive)
Hey builders! ๐Ÿ‘จโ€๐Ÿ’ป
Most of you have seen the previous post about the Euler Private Credit Facility and how it's generating 20-33% APY for whitelisted participants. But today we're going DEEP on the technical implementationโ€”how you actually DEPLOY one of these things.
This is for:
๐Ÿ—๏ธ Protocol developers building similar systems
๐Ÿ”ง DevOps engineers managing DeFi infrastructure
๐Ÿง  Technical enthusiasts who want to understand how institutional DeFi actually works
๐Ÿ“Š Risk managers who need to audit these systems
If you're not technical, this might be dense. But stick aroundโ€”understanding the deployment process reveals a lot about the security and risk management involved.
Let's build! ๐Ÿš€
๐ŸŽฏ What We're Actually Deploying
The Euler Private Credit Facility isn't just "one smart contract." It's an orchestrated system of multiple components working together:
The Core Stack:
โœ… EulerRouter: Oracle routing and configuration manager
โœ… HookTargetAccessControl: The whitelist bouncer + emergency pause system
โœ… FixedRateIRM: The interest rate model (that magical 0.25% APY)
โœ… EVault: The actual lending vault (deployed via factory)
โœ… PendlePtOracleAdapter: Connects Pendle markets to Euler ecosystem
Think of it like deploying a bank, except it's all code and one mistake could drain millions. No pressure! ๐Ÿ˜…
๐Ÿ“‹ The Four-Phase Deployment Process
Professional DeFi deployments follow a RIGOROUS process. You don't just "yeet contracts to mainnet and hope for the best."
Here's how it actually works:
๐Ÿ”ฌ Phase 1: Pre-Deployment Validation (The "Please God Don't Get Rekt" Phase)
Before touching mainnet, you validate EVERYTHING in a controlled environment.
Step 1: Unit Testing with Foundry
bashforge test
This runs your entire test suite. You're checking:
โœ… Hook configurations work correctly
โœ… IRM (Interest Rate Model) calculates rates properly
โœ… Oracle wiring is correct
โœ… Access control logic functions as expected
โœ… Edge cases don't cause reverts
If ANY test fails, you do NOT proceed. Period. ๐Ÿ›‘
Step 2: Mainnet Fork Simulations
This is where it gets real. You spin up a fork of mainnet with current state and run your deployment script against it.
bashforge test --fork-url $MAINNET_RPC_URL
You're running ForkDeploymentTest.t.sol which simulates:
The entire deployment sequence
Oracle initialization
Governance handoff
Whitelisting operations
Actual deposit/withdraw/borrow operations
Why fork testing matters:
Real mainnet state (actual Chainlink feeds, actual Pendle markets)
Catches integration issues you'd never see in unit tests
Lets you verify gas costs
Allows you to test against actual oracle latency
Step 3: Dry-Run Deployment
Run your deployment script (DeployFullSystem.s.sol) WITHOUT broadcasting to mainnet:
bashforge script DeployFullSystem.s.sol --rpc-url $MAINNET_RPC_URL
This simulates the deployment and logs all the addresses and parameters. You're checking:
โœ… No reverts during deployment
โœ… Constructor arguments are correct
โœ… All addresses look reasonable (not zero address, etc.)
โœ… Gas costs are within budget
Step 4: Consistency Checks
Before you broadcast, triple-check:
๐Ÿ“ Multisig address is correct (seriously, verify this 10 times)
๐Ÿ“ FIXED_RATE_APY_BPS matches your desired rate:
25 bps = 0.25% APY
200 bps = 2.00% APY
๐Ÿ“ LTV ratios align with risk parameters
๐Ÿ“ Chainlink feed addresses are correct for your network
๐Ÿ“ Pendle market addresses are verified
One wrong address = funds potentially lost forever. Check everything. โš ๏ธ
๐Ÿš€ Phase 2: Mainnet Deployment and Governance Handoff
Okay, validation passed. Now we're going to mainnet.
Step 1: Broadcast Deployment
bashforge script DeployFullSystem.s.sol --rpc-url $MAINNET_RPC_URL --broadcast --verify
The --broadcast flag actually sends transactions to mainnet.
The --verify flag auto-verifies contracts on Etherscan.
What happens:
EulerRouter deploys
HookTargetAccessControl deploys
FixedRateIRM deploys
EVault factory creates the vault
PendlePtOracleAdapter deploys
All components get wired together
Initial State:
Deployer owns Hook, IRM, and PT Adapter
Vault governor = deployer
Router governance = deployer
This is temporary. We're about to hand this over to the multisig.
Step 2: The Two-Step Ownership Transfer
Here's where Euler's security model shines. They use Ownable2Step instead of regular Ownable.
Why two-step matters:
With regular Ownable:
soliditytransferOwnership(newOwner);
// Ownership transfers IMMEDIATELY
// If newOwner is wrong address = permanently locked
With Ownable2Step:
solidity// Step 1: Deployer proposes transfer
transferOwnership(multisigAddress);
// Step 2: Multisig must ACCEPT
multisig.acceptOwnership();
// Only transfers if multisig confirms
What this prevents:
โŒ Typos in multisig address
โŒ Transfers to contracts that can't accept ownership
โŒ Accidental burns to zero address
Deployment sequence:
Deployer transfers ownership of Hook, IRM, and PT Adapter to multisig
solidity hook.transferOwnership(MULTISIG_ADDRESS);
irm.transferOwnership(MULTISIG_ADDRESS);
ptAdapter.transferOwnership(MULTISIG_ADDRESS);
Multisig must call acceptOwnership() on each contract
solidity // Multisig executes:
hook.acceptOwnership();
irm.acceptOwnership();
ptAdapter.acceptOwnership();
Set vault governor and router governance to multisig
solidity vault.setGovernor(MULTISIG_ADDRESS);
router.setGovernance(MULTISIG_ADDRESS);
Only after all these confirmations is the handoff complete. ๐Ÿ”
โฐ Phase 3: Oracle Initialization (THE MOST CRITICAL PHASE)
This is where most projects fuck up. Oracle initialization for Pendle markets has VERY specific requirements.
The 30-Minute Rule โฑ๏ธ
Pendle uses TWAP (Time-Weighted Average Price) oracles. These need observation data points across time to work.
The Problem:
When you first deploy, the oracle has ZERO observations. You literally cannot use it yet.
The Solution:
Step 1: Increase Cardinality
For each Pendle market you want to support, call:
solidityIPMarket(pendleMarket).increaseObservationsCardinalityNext(newCardinality);
This increases the oracle's storage capacity for observations. Think of it like making the buffer bigger.
Step 2: Wait 30 Minutes โฐ
YOU MUST WAIT AT LEAST 30 MINUTES.
During this time, the Pendle oracle is accumulating price observations. Each block adds data points.
If you try to enable borrowing before 30 minutes:
Error: OracleNotReady
Your transaction reverts. The system literally won't let you proceed.
Why 30 minutes matters:
TWAP needs multiple observations across time to calculate a reliable average. With only 1-2 observations, the price could be manipulated via flash loans or MEV.
With 30 minutes of observations:
โœ… Covers ~150 blocks (Ethereum)
โœ… Smooths out volatility
โœ… Prevents manipulation
โœ… Creates reliable price data
Step 3: Configure LTV Ratios
Once the oracle is ready, configure the risk parameters:
Standard Configuration:
Borrow LTV: 75% (you can borrow up to 75% of collateral value)
Liquidation LTV: 82% (you get liquidated at 82%)
Conservative Stablecoin Configuration:
Borrow LTV: 80%
Liquidation LTV: 85%
The buffer between borrow and liquidation LTV is your safety margin. The wider the gap, the safer (but lower capital efficiency).
Example:
solidity// Set LTV for PT-sUSDe collateral
vault.setLTV(
PT_SUSDE_ADDRESS,
8000, // 80% borrow LTV (in basis points)
8500, // 85% liquidation LTV
0 // No ramp duration
);
๐Ÿ‘ฅ Phase 4: Whitelisting (Access Control)
Now we populate the whitelist. Remember, this is a PERMISSIONED facility.
Two Separate Whitelists:
1. User Whitelist (Borrowers & Lenders)
solidityhook.batchSetUserWhitelist(
[user1, user2, user3, ...],
true // enable
);
These addresses can:
โœ… Deposit collateral
โœ… Borrow USDC
โœ… Repay loans
โœ… Withdraw collateral
2. Liquidator Whitelist
solidityhook.batchSetLiquidatorWhitelist(
[liquidator1, liquidator2, liquidator3],
true // enable
);
These addresses can:
โœ… Liquidate undercollateralized positions
โœ… Earn liquidation bonuses
โœ… Keep the system solvent
The OP_TRANSFER Hook (Critical Security Feature) ๐Ÿ”’
Here's something clever: the hook doesn't just control deposits and borrows. It also hooks OP_TRANSFER.
Why this matters:
Without this hook, someone could:
Get whitelisted
Deposit and receive vault shares (sTokens)
Transfer those shares to a non-whitelisted address
Bypass access controls entirely
With the OP_TRANSFER hook:
Vault shares CANNOT be transferred to non-whitelisted addresses
The whitelist becomes truly enforceable
No backdoor escapes
This is institutional-grade access control. ๐Ÿ’ช
โš ๏ธ Critical Risk Vectors and Mitigation
Now that we understand deployment, let's talk about what can go wrong:
Risk 1: The Liquidation Paradox
The Problem:
Liquidators must be whitelisted
If NO liquidators are whitelisted = bad debt accumulates
If whitelisted liquidators lack capital = positions can't be liquidated
Bad debt spirals, protocol becomes insolvent
The Mitigation:
โœ… Whitelist MULTIPLE liquidators (redundancy)
โœ… Ensure liquidators have sufficient USDC reserves
โœ… Monitor liquidator health regularly
โœ… Have backup liquidators on standby
โœ… Consider protocol-owned liquidator (treasury funds)
Risk 2: Oracle Readiness Failure
The Problem:
You enable borrowing before the 30-minute observation window completes
Oracle returns stale or manipulable data
Positions get liquidated incorrectly OR manipulation occurs
The Mitigation:
โœ… NEVER enable borrowing until oracle is confirmed ready
โœ… Test oracle reads in dry-run environment first
โœ… Monitor oracle freshness continuously
โœ… Set up alerts for oracle failures
Risk 3: PT Expiry Edge Cases
The Problem:
PT tokens have MATURITY DATES. When they mature:
The PT token converts to underlying asset
Collateral value might change
Positions need to be closed or rolled
If positions are open when PT expires:
Could trigger PtExpired state
Liquidation logic might behave unexpectedly
Users might be unable to manage positions
The Mitigation:
๐Ÿ“… Track ALL PT maturity dates
๐Ÿ“… Set up alerts 7 days, 3 days, 1 day before expiry
๐Ÿ“… Force-close or roll positions before maturity
๐Ÿ“… Communicate with users about upcoming expiries
๐Ÿ“… Consider auto-settlement mechanisms
Risk 4: Governance Key Management
The Problem:
The multisig controls EVERYTHING:
Interest rate changes
Emergency pause
Whitelist management
LTV adjustments
Supply/borrow caps
If the multisig is compromised:
Attacker could drain the vault
Change rates to 100%
Whitelist themselves
Disable safety mechanisms
The Mitigation:
๐Ÿ” Use hardware wallets for all signers
๐Ÿ” Require 3-of-5 or 4-of-7 (not 2-of-3)
๐Ÿ” Implement timelocks for critical operations
๐Ÿ” Monitor multisig activity 24/7
๐Ÿ” Have emergency response playbook
๐Ÿ” Consider rotating signers periodically
๐ŸŽฏ The Post-Deployment Checklist
Before you call the deployment "successful" and go to sleep, verify ALL of these:
โœ… Contract Verification
All contracts verified on Etherscan
Constructor arguments are visible
Source code matches deployment
ABI is accessible
โœ… Ownership Confirmation
Multisig has accepted ownership of Hook
Multisig has accepted ownership of IRM
Multisig has accepted ownership of PT Adapter
Vault governor is set to multisig
Router governance is set to multisig
Deployer has NO remaining admin privileges
โœ… Oracle Validation
30+ minutes have elapsed since cardinality increase
Oracle returns non-zero prices
Oracle updates are within heartbeat interval
TWAP is functioning correctly
Chainlink feeds are healthy
โœ… Smoke Testing
Conduct actual transactions with a whitelisted test account:
Deposit USDC as lender (receive sTokens)
Deposit PT as collateral
Borrow small amount of USDC
Repay partial debt
Withdraw partial collateral
Check all balances are correct
Verify interest accrual
Test liquidation with underwater position (on testnet/fork)
โœ… Risk Parameter Documentation
Fixed rate is documented (0.25% or 2.0%)
LTV ratios are documented per collateral type
Supply caps are set and documented
Borrow caps are set and documented
Liquidation bonus is configured
Oracle parameters are recorded
โœ… Monitoring Setup
Oracle freshness alerts configured
PT expiry date alerts configured
Liquidation threshold alerts configured
Multisig activity monitoring enabled
TVL/utilization dashboards created
On-call rotation established
Only when ALL checkboxes are ticked is the deployment complete. ๐Ÿ“‹
๐Ÿง  Governance Operations (Ongoing Management)
Deployment is just the beginning. Here's what the multisig needs to do post-launch:
Rate Adjustments
Market conditions change. The multisig might need to adjust rates:
solidity// Change from 0.25% to 0.50% APY
fixedRateIRM.setRate(50); // 50 bps
When to change rates:
Market rates have shifted significantly
Attracting more lenders requires higher rates
Risk profile has changed
Competitive landscape has evolved
Emergency Pausing
If shit hits the fan:
solidityhook.setPaused(true);
This immediately stops:
โŒ New deposits
โŒ New borrows
โœ… Allows repayments (users can deleverage)
โœ… Allows withdrawals (users can exit)
When to pause:
Oracle failures
Suspected exploit
Pendle market issues
Regulatory concerns
Protocol upgrades
Capacity Management
Control total exposure to prevent over-concentration:
solidityvault.setCaps(
supplyCapUSDC, // Max USDC deposits
borrowCapUSDC // Max USDC borrows
);
Why caps matter:
Limit total risk exposure
Prevent any single market from dominating
Create room for phased scaling
Allow for emergency capacity reduction
๐Ÿ’ก Pro Tips from Production Deployments
Tip 1: Deploy to Testnet First (Obviously)
But not just "deploy and check it worked." Actually USE it on testnet for a week:
Have team members interact with it
Try to break it
Test edge cases
Verify monitoring works
Practice emergency procedures
Tip 2: Time Your Mainnet Deployment
Deploy during:
โœ… Low network congestion (lower gas costs)
โœ… Business hours in your timezone (in case issues arise)
โœ… When your entire team is available
โœ… NOT right before a weekend/holiday
Deploy in phases:
Day 1: Deploy contracts, verify, hand off to multisig
Day 2: Initialize oracles, wait 30 minutes
Day 3: Configure parameters
Day 4: Whitelist initial users
Day 5: Enable with caps, monitor closely
Week 2: Gradually increase caps
Tip 3: Document EVERYTHING
Create a deployment journal:
Every transaction hash
Every address
Every parameter choice
Rationale for decisions
Issues encountered and resolutions
Future you (during an incident) will thank past you.
Tip 4: Have a Rollback Plan
What if something goes wrong 6 hours after deployment?
Can you pause the system? (Yes, via hook)
Can you prevent new borrows? (Yes, via pause)
Can users exit? (Yes, withdrawals work even when paused)
Can you migrate to a new deployment? (Maybe, but complex)
Know your escape hatches BEFORE you need them.
Tip 5: Monitor Continuously
Set up alerts for:
๐Ÿ“Š TVL changes >10% in 1 hour
๐Ÿ“Š Utilization >90%
๐Ÿ“Š Oracle price changes >5% in 15 minutes
๐Ÿ“Š Liquidations occurring
๐Ÿ“Š Multisig transactions
๐Ÿ“Š Contract interactions from unknown addresses
Use tools like:
Tenderly for monitoring
Defender for automated actions
PagerDuty for on-call alerts
Dune Analytics for dashboards
๐ŸŽฌ The Big Picture: Why This Process Matters
You might be thinking: "This seems like overkill for deploying some smart contracts."
It's not.
These systems handle MILLIONS of dollars. One mistake could:
Drain user funds
Create bad debt
Trigger liquidation cascades
Destroy reputation
Lead to legal liability
The multi-phase deployment process isn't bureaucracyโ€”it's insurance.
Comparison:
Degen Deployment:
Write code
Test locally
YOLO to mainnet
Hope for the best
Get exploited in 48 hours
Professional Deployment:
Comprehensive unit tests
Fork testing against mainnet state
Dry-run deployment verification
Phased mainnet deployment
Two-step governance handoff
Oracle initialization with mandatory waiting period
Smoke testing with real transactions
Continuous monitoring
Emergency procedures ready
Which would you trust with your money? ๐Ÿ’ฐ
๐Ÿ”ฎ Future Considerations
As these facilities evolve, watch for:
1. Automated Liquidation Systems
Currently, liquidators are whitelisted humans/bots. Future versions might have:
Protocol-owned liquidators (treasury-funded)
Dutch auction liquidation mechanisms
Automated deleveraging (like perp exchanges)
2. Dynamic Rate Adjustment
Fixed rates are great, but they might need adjustment. Future versions could:
Adjust rates based on treasury yield changes
Implement rate corridors (0.25%-0.50%)
Use governance-approved rate curves
3. Multi-Collateral Support
Currently optimized for PT tokens. Could expand to:
Multiple PT types simultaneously
RWA tokens
Other yield-bearing assets
Cross-collateral positions
4. Cross-Chain Deployment
Euler v2 is designed for multi-chain. Expect:
Base deployments
Arbitrum deployments
Optimism deployments
L2-specific optimizations
๐Ÿ“š Key Takeaways for Builders
If you're building similar systems:
โœ… Never skip the 30-minute oracle initialization window - this is non-negotiable
โœ… Use Ownable2Step for all critical contracts - prevents catastrophic ownership mistakes
โœ… Hook OP_TRANSFER operations - otherwise whitelists are bypassable
โœ… Have multiple whitelisted liquidators - single points of failure are deadly
โœ… Track PT expiry dates religiously - set up alerts and automation
โœ… Deploy in phases with increasing caps - don't go 0 to $100M TVL overnight
โœ… Document everything - your future incident response depends on it
โœ… Test on forks with real mainnet state - unit tests aren't enough
๐Ÿ—ฃ๏ธ Discussion for the Technical Community
Questions for the builders out there:
What additional safety checks would you add to this deployment process?
How would you design an automated liquidation system for whitelisted-only environments?
What monitoring metrics are most critical for this type of facility?
How would you handle PT rollovers (migrating from expiring PT to new PT)?
What's your take on fixed-rate vs. variable-rate models for institutional DeFi?
Let's discuss! Share your deployment war stories below. ๐Ÿ‘‡
Not deployment advice. Every protocol is different. Audit your code. Test extensively. Have multiple people review. Monitor continuously. And when in doubt, pause first, ask questions later. ๐Ÿ™
1:54
1
0 comments
David Zimmerman
6
๐Ÿ› ๏ธ Behind the Scenes: How to Deploy a $XXM Private Credit Facility (Technical Deep-Dive)
DeFi University
skool.com/defiuniversity
Master DeFi from beginner to advanced. Security-first curriculum, live mentorship, gamified learning. Join us and build DeFi expertise safely.
Leaderboard (30-day)
Powered by