Development of an Aave Fork for Custom Lending
Forking Aave V3 is not downloading the repository and changing parameters. The Aave V3 codebase contains 47 main contracts, 15,000+ lines of Solidity, a non-trivial role system and three different proxy patterns. Most "forks" we've audited broke in one of three places: incorrect PoolAddressesProvider configuration, broken interest rate model, or disabled oracleType check when adding a new asset. Any of these errors — potential fund drain.
Where Fork Developers Most Often Make Mistakes
PoolAddressesProvider and Roles
Aave V3 uses PoolAddressesProvider as the central registry of all system contract addresses. Proper initialization of all roles is critical when deploying a fork:
-
POOL_ADMIN— adds assets, changes risk parameters -
EMERGENCY_ADMIN— can pause market during attack -
RISK_ADMIN— changes liquidation threshold and LTV -
FLASH_BORROWER— whitelist for zero flash loan fee -
ASSET_LISTING_ADMIN— listing new assets
We've seen forks where all roles were on a single EOA without timelock. One compromised key — and the attacker changes oracle to their own contract, lists fake asset with high LTV, borrows all real assets.
Correct configuration: POOL_ADMIN and RISK_ADMIN — Gnosis Safe 3-of-5 with 48-hour timelock. EMERGENCY_ADMIN can be 2-of-3 without timelock (need quick response during attack).
Interest Rate Model: Calculation and Parameters
Aave uses a piecewise-linear rate model with optimal utilization. Below OPTIMAL_USAGE_RATIO, rate grows slowly; above — exponentially. Model parameters for each asset:
if (utilization < OPTIMAL_USAGE_RATIO):
borrowRate = baseVariableBorrowRate + (utilization / OPTIMAL_USAGE_RATIO) * variableRateSlope1
else:
excessUtil = utilization - OPTIMAL_USAGE_RATIO
borrowRate = baseVariableBorrowRate + variableRateSlope1 + (excessUtil / (1 - OPTIMAL_USAGE_RATIO)) * variableRateSlope2
Parameter errors — either rates too low (LPs don't get fair yield) or too high during stress (cascade liquidations). For custom assets we calibrate parameters based on historical volatility and liquidity depth on CEX/DEX.
EMode and Isolated Assets
Aave V3 introduced two important mechanisms:
Efficiency Mode (eMode) — lets you set a category of correlated assets (e.g., all stablecoins or ETH derivatives). Within category LTV can be 95%+ because liquidation risk from price movement is minimal. Improper eMode setup — users borrow more than they should.
Isolation Mode — an asset is available as collateral only in isolation (cannot mix with others). Important for long-tail assets with low liquidity.
What and Why We Change in a Fork
Custom Oracle Layer
If forking for Polygon, Arbitrum or zkSync — Chainlink Data Feeds are available, but not for all assets. For unlisted assets you need a custom oracle. Aave V3 uses IPriceOracleGetter interface — just implement getAssetPrice(address asset) and register in AaveOracle.
For new assets we build a composite oracle: primary source — Chainlink (if available), fallback — Uniswap V3 TWAP 30 minutes. If sources diverge >5% — circuit breaker, liquidations temporarily stop.
Adapted Reserve Factor
Reserve factor — percentage of interest income going to protocol treasury. In original Aave it ranges from 10% (stablecoins) to 20–35% (more volatile assets). In a fork you can configure differently: e.g., 50% to treasury + 50% to insurance module for bad debt protection.
Modified Liquidation Parameters
For a custom fork targeting a specific niche (e.g., NFT-collateralized lending), standard liquidation parameters don't work. NFTs are illiquid, instant liquidation impossible. Need auction mode: liquidator opens auction, after 24–48 hours takes asset. Requires full rework of LiquidationLogic.sol.
Fork Development Stack
We work with Aave V3 codebase from tag v3.0.1 or current version at project start. Don't take unfixed main — production uses only verified version.
Foundry fork tests — foundation of QA. For each changed module we write tests against real Aave V3 on mainnet: verify behavior matches for standard operations and custom logic works only where needed.
# Test liquidation on mainnet fork
forge test --fork-url $ETH_MAINNET_RPC --match-test testLiquidationWithCustomOracle -vvvv
For frontend — Aave V3 Utilities SDK adapts to custom parameters. wagmi + viem for wallet connection. The Graph subgraph for historical position data.
Deployment Networks
| Network | Gas Cost | Chainlink Feeds | Features |
|---|---|---|---|
| Ethereum Mainnet | High | Full Set | Maximum arbitrage liquidity |
| Arbitrum One | Low | Good Set | L2, cheap liquidations |
| Polygon PoS | Low | Good Set | Wide audience |
| Base | Low | Growing Set | Coinbase ecosystem |
| zkSync Era | Very Low | Limited | ZK proof verification |
Development Process
Analytics (1 week). Define which assets to list, what risk parameters needed, need eMode categories, what oracle layer fits target network.
Fork and Adaptation (2–3 weeks). Deploy and configure PoolAddressesProvider, adapt oracle layer, customize risk parameters, setup governance roles.
Testing (1–2 weeks). Fork tests of all operations. Stress tests: Black Thursday simulation (ETH -40% per hour). Echidna property tests: solvency invariant unbroken under any operation sequence.
Audit (2–4 weeks). For fork with changed modules — mandatory external audit of modifications. For deploy with minimal changes — audit of configuration and parameters.
Deployment and Launch. Staged: first testnet (Sepolia/Arbitrum Goerli), then mainnet with limited caps, gradual cap removal as TVL grows.
Timeline Guidance
Fork with minimal changes (parameters only, new oracle) — 3–5 weeks. Fork with custom liquidation mechanism or eMode configuration — 6–10 weeks. Fork for non-standard collateral (NFT, RWA) — 10+ weeks including specialized liquidation engine development.







