Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Design a Dynamic Fee Model

A technical guide for developers on implementing dynamic fee mechanisms. Covers base fee algorithms, tiered structures, and Solidity code for adjusting fees based on network demand.
Chainscore © 2026
introduction
A PRACTICAL GUIDE

How to Design a Dynamic Fee Model

A step-by-step framework for implementing adaptive transaction pricing in DeFi protocols and blockchain applications.

A dynamic fee model adjusts transaction costs algorithmically based on real-time network conditions, such as congestion, asset volatility, or pool utilization. Unlike static fees, which remain fixed, dynamic models optimize for protocol objectives like stable revenue, user retention, and efficient resource allocation. The core design challenge is balancing predictability for users with the flexibility needed to respond to market shifts. Common applications include Automated Market Makers (AMMs) like Uniswap V3, which uses tiered fees, and Layer 2 rollups, which adjust fees based on Ethereum mainnet gas prices.

Designing an effective model starts with defining clear key performance indicators (KPIs). These metrics determine what the fee algorithm should respond to. For a lending protocol, the primary KPI might be utilization rate—the percentage of total deposits that are borrowed. High utilization indicates high demand and potential liquidity shortages, warranting a fee increase to incentivize more deposits. For a DEX, the KPI could be pool imbalance or volatility, where higher instability increases the risk for liquidity providers, justifying higher fees as compensation. The chosen KPIs must be measurable on-chain and resistant to manipulation.

The next step is selecting a mathematical function to map your KPI to a fee rate. A linear function is simple but can lead to abrupt changes. A sigmoid or exponential function creates a smoother, more predictable curve, gradually increasing fees as the KPI approaches a target threshold. For example, a liquidity pool might use a function where the fee f(u) is defined as: f(u) = baseFee + (maxFee - baseFee) * (u / targetUtilization)^k. Here, u is the current utilization, baseFee is the minimum rate, maxFee is a cap, and k is an exponent controlling the curve's steepness. The targetUtilization is a critical parameter defining the "ideal" state.

Parameter tuning is crucial and often requires simulation and historical analysis. Using tools like Python with pandas or specialized agent-based simulators, you can backtest your fee function against historical blockchain data. The goal is to calibrate parameters (like baseFee, maxFee, and k in the previous example) to achieve desired outcomes: maximizing protocol revenue without deterring users, or maintaining pool stability during market shocks. Forks of successful protocols like Balancer or Curve offer valuable real-world data points for initial parameter estimates.

Finally, the model must be implemented securely in a smart contract. The fee calculation logic should be gas-efficient and, where possible, avoid complex math operations that are expensive on-chain. Use oracles like Chainlink for off-chain data (e.g., volatility indexes) if your KPI requires it, but be mindful of oracle latency and attack vectors. Always include circuit breakers or fee caps to prevent the algorithm from setting fees to extreme values during unexpected events. A timelock or governance mechanism for adjusting core parameters is also a best practice for decentralized control.

Successful dynamic fee models are iterative. After deployment, continuous monitoring via dashboard analytics (e.g., Dune Analytics, The Graph) is essential to track fee revenue, user volume, and KPI correlations. Be prepared to propose governance updates to parameters as the market evolves. The end goal is a self-regulating system that enhances protocol resilience and creates a better, more efficient experience for all participants.

prerequisites
DESIGNING A DYNAMIC FEE MODEL

Prerequisites for Implementation

Before writing a single line of code, a successful dynamic fee model requires a clear understanding of your protocol's economic goals, the data it can access, and the technical constraints of its environment.

The first prerequisite is defining your economic objectives. Are you prioritizing protocol revenue, liquidity provider (LP) incentives, or user experience? A model for a decentralized exchange (DEX) like Uniswap V3, which uses concentrated liquidity, has different goals than a lending protocol like Aave, which manages borrowing risk. You must decide on the core levers: should fees increase with volatility to compensate LPs for impermanent loss, or decrease with high volume to attract more traders? Document these goals explicitly, as they will directly inform your algorithm's parameters and logic.

Next, identify and secure access to real-time, reliable on-chain data. A dynamic model cannot function without accurate inputs. Common data sources include: - Chainlink oracles for asset prices and volatility indices. - Protocol-specific metrics like pool utilization rate (for lending), total value locked (TVL), or 24-hour trading volume (for DEXs). - Gas price feeds from services like Etherscan or the blockchain client itself, if adjusting for network congestion. Your smart contracts must have permissioned, trust-minimized access to this data, often via oracle interfaces or authenticated internal state variables.

You must also understand the technical and economic constraints of your deployment chain. On high-throughput chains like Solana or Avalanche, you can afford more frequent fee updates with minimal cost. On Ethereum Mainnet, each storage write is expensive, so your model might update fees only per block or epoch to conserve gas. Furthermore, consider the tokenomics of your fee token. If fees are paid in a volatile native token, your model may need a stabilization mechanism, such as pegging the fee rate to a stablecoin value or implementing a moving average to smooth out price spikes.

Finally, design with upgradability and governance in mind from the start. A poorly tuned fee model can drive users away. Implement a timelock-controlled parameter adjustment function or a fully on-chain governance module (e.g., using OpenZeppelin's Governor contract) to allow for future optimization. For critical parameters, consider a circuit breaker that can freeze fee changes if they exceed safe bounds. Your initial implementation should be deployed on a testnet with comprehensive simulations, using historical data to stress-test the model under various market conditions before mainnet launch.

key-concepts-text
FEE MARKET DESIGN

How to Design a Dynamic Fee Model

Dynamic fee models adjust transaction costs in real-time based on network demand, creating an efficient market for block space. This guide explains the core components and implementation strategies.

A dynamic fee model replaces fixed or simple auction fees with an algorithm that responds to network conditions. The primary goal is to optimize throughput and user experience by reducing fee volatility while ensuring validators are compensated for prioritizing transactions. Key inputs typically include the mempool size, historical fee data, and the target block fullness. Unlike EIP-1559's base fee, a fully dynamic model can incorporate more variables and adjust more frequently, even within a single block.

Designing the model starts with selecting the right oracles and metrics. You need reliable, manipulation-resistant data sources. Common inputs are: the average fee paid in recent blocks, the pending transaction count, and the rate of block space consumption. For L2s or app-chains, you might also factor in sequencer load or data availability costs. The model's update frequency is critical; updating every block provides responsiveness but can lead to instability, while slower updates may not capture sudden demand spikes.

The core algorithm often uses a PID controller or a exponential moving average to smooth inputs and calculate a new base fee. For example, if the target block gas used is 15 million and the last block was 90% full, the fee might increase by a small percentage. The formula baseFee_{n+1} = baseFee_{n} * (1 + (gasUsed_{n} - target) / target / 8) is a simplified version of EIP-1559's adjustment. More complex models might add a term for mempool growth rate. Always implement fee caps (minimum and maximum) to prevent extreme outcomes.

Implementation requires careful integration with your chain's execution client. You must modify the transaction validation logic to accept the dynamic fee and the block production logic to apply it. For EVM chains, this often means overriding the BASE_FEE opcode behavior. Thorough testing with historical load simulations and stress tests is non-negotiable. Observe how the model behaves during a flash loan attack or a popular NFT mint to ensure fees rise appropriately without imposing unreasonable costs on ordinary users.

Finally, parameter tuning is an ongoing process. The initial target block usage, adjustment denominator (the 8 in the formula above), and fee caps must be calibrated for your chain's specific usage patterns. Monitor key outcomes: fee predictability, validator revenue stability, and mempool clearance time. Be prepared to adjust parameters via governance or a pre-programmed schedule. A well-tuned dynamic fee model is a major competitive advantage, offering users reliable and fair pricing for blockchain resources.

fee-model-types
FEE DESIGN

Types of Dynamic Fee Mechanisms

Dynamic fee models adjust transaction costs based on real-time network conditions. This guide explores the core mechanisms used by major protocols.

01

Time-Based Decay

Fees decrease over time to incentivize early participation or penalize stale orders. This is common in auction-based systems like Dutch auctions.

  • Example: An NFT mint starts at 1 ETH and linearly decays to 0.1 ETH over 24 hours.
  • Use Case: Optimism's RetroPGF funding rounds use a time-decaying voting mechanism to prioritize early, high-signal contributions.
  • Implementation: Requires an on-chain clock or block number tracker to calculate the current fee tier.
02

Utilization-Based Pricing

Fees scale directly with the utilization rate of a shared resource, such as a lending pool or bridge liquidity.

  • Formula: Often follows a piecewise linear or kinked model (e.g., Compound's interest rate model).
  • Example: Aave increases borrowing rates sharply after pool utilization exceeds an 80% optimal threshold.
  • Key Metric: The utilization ratio (borrowed/supplied) is the primary input. This mechanism efficiently allocates scarce capital during high demand.
03

Congestion-Based (EIP-1559)

A base fee is algorithmically adjusted per block based on network congestion, with users adding a priority tip for faster inclusion. This is the standard on Ethereum, Polygon PoS, and Avalanche C-Chain.

  • Base Fee: Burned; dynamically targets 50% block fullness.
  • Priority Fee (Tip): Paid to the validator/miner.
  • Design Insight: The base fee update formula uses an exponential moving average of block size to smooth volatility.
04

Multi-Dimensional Auctions

Fees are determined by bidding across multiple parameters beyond just price. Used in MEV (Maximal Extractable Value) auctions like those facilitated by Flashbots.

  • Parameters: Bid amount, transaction ordering, bundle complexity, and inclusion guarantees.
  • Protocol Example: Flashbots Protect allows users to submit transactions with a bid for block space, competing with MEV searchers.
  • Outcome: Creates a market for transaction ordering, moving value from opaque MEV to explicit user payments.
05

Stake-Weighted Fee Discounts

Users receive fee discounts or rebates proportional to their protocol stake or governance token holdings. This aligns user incentives with long-term protocol health.

  • Implementation: dYdX used a staked token model for fee discounts on trades.
  • Mechanism: Fee = Base Rate * (1 - Discount Tier). Discount tiers are based on staked token amount thresholds.
  • Consideration: Must balance fairness for small users against benefits for large stakeholders to avoid centralization.
06

Activity-Based Rebates

Fees are charged upfront but partially refunded based on user behavior that benefits the ecosystem. This rewards desired actions like providing liquidity or long-term holding.

  • Example: A DEX might charge a 0.3% swap fee but rebate 0.1% to liquidity providers of the traded pair.
  • GMX's Model: Trading fees on GMX are distributed to GLP stakers (liquidity providers) and GMX stakers (protocol backers).
  • Design Goal: Use fee revenue to directly subsidize and incentivize critical protocol functions.
IMPLEMENTATION APPROACHES

Dynamic Fee Mechanism Comparison

Comparison of common algorithmic designs for adjusting protocol fees based on network conditions.

MechanismExponential Moving Average (EMA)Time-Weighted Average Price (TWAP)PID Controller

Primary Use Case

Smoothing short-term volatility

Oracle price reference for DeFi

Precise targeting of system metrics

Reaction Speed

Fast (configurable decay)

Slow (depends on window)

Variable (tunable gains)

Gas Cost

Low (O(1) update)

High (O(n) historical data)

Medium (O(1) with state)

Parameter Complexity

Low (1-2 params: alpha, window)

Medium (window size, granularity)

High (3 params: Kp, Ki, Kd)

Resilience to Manipulation

Medium

High (with long windows)

Low (without safeguards)

On-Chain Proven

Example Protocols

Uniswap V3, GMX

Chainlink, Uniswap V2

MakerDAO (historical)

implementation-steps
TUTORIAL

Implementation Steps and Code Examples

A practical guide to implementing a dynamic fee model for a decentralized exchange or DeFi protocol, from core logic to on-chain integration.

A dynamic fee model adjusts transaction costs based on real-time on-chain conditions. The core logic typically involves a base fee and a variable component driven by metrics like pool utilization, volatility, or network congestion. For a DEX, a common approach is to increase fees when a liquidity pool's utilization is high to manage capital efficiency and impermanent loss. You can model this with a piecewise linear function or a continuous curve, such as fee = baseFee + (utilizationRatio * k), where k is a scaling constant. The key is to define the fee parameters (base, min, max) and the triggering metric programmatically.

Here is a simplified Solidity example for a dynamic fee based on a liquidity pool's utilization. This contract snippet calculates a fee that scales linearly between a minimum and maximum bound as utilization increases. The getDynamicFee function is callable by the pool's swap logic.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract DynamicFeeModel {
    uint256 public constant MIN_FEE = 5; // 0.05%
    uint256 public constant MAX_FEE = 30; // 0.30%
    uint256 public constant MAX_UTILIZATION = 80; // 80%

    function getDynamicFee(uint256 utilized, uint256 total) public pure returns (uint256) {
        uint256 utilization = (utilized * 100) / total;
        if (utilization >= MAX_UTILIZATION) {
            return MAX_FEE;
        }
        // Linear interpolation: fee = MIN_FEE + (utilization/MAX_UTILIZATION) * (MAX_FEE - MIN_FEE)
        uint256 variableFee = ((MAX_FEE - MIN_FEE) * utilization) / MAX_UTILIZATION;
        return MIN_FEE + variableFee;
    }
}

This basic model protects liquidity during high demand. In production, you would use a more robust math library like PRBMath to avoid precision loss and potentially implement a non-linear curve.

For a more sophisticated model, consider using an exponential moving average (EMA) of volume or volatility to smooth out short-term spikes and prevent fee manipulation. You can store the EMA state in storage and update it with each block. Another advanced technique is time-weighted averaging, used by protocols like Uniswap V3 for oracle prices, which can be adapted to calculate a stable fee rate over a window (e.g., 24 hours). Always ensure your fee calculation is gas-efficient and uses secure math operations to prevent overflows—libraries like OpenZeppelin's SafeCast and SafeMath (for older versions) are essential.

Integrating the fee model requires careful architectural decisions. The fee logic should be in a separate, upgradeable contract (using a proxy pattern like Transparent or UUPS) to allow for parameter adjustments without migrating liquidity. The main protocol contract (e.g., the AMM pool) will call this fee contract via an interface. Emit events on fee updates for off-chain monitoring. Thoroughly test the model using a framework like Foundry or Hardhat, simulating edge cases: zero utilization, 100% utilization, flash loan attacks, and oracle manipulation attempts. Fuzz testing can help discover unexpected integer overflow scenarios.

Finally, parameter tuning is critical and often requires simulation. Use historical on-chain data from providers like The Graph or Dune Analytics to backtest your fee formula against past market conditions. Tools like Gauntlet and Chaos Labs offer agent-based simulations to stress-test economic models. Start with conservative parameters on a testnet and consider implementing a timelock-controlled governance mechanism for future adjustments. A well-designed dynamic fee model enhances protocol resilience, optimizes revenue for liquidity providers, and improves the trading experience by aligning costs with real-time network value.

IMPLEMENTATION PATTERNS

Code Examples by Use Case

Constant Product AMM with Dynamic Fees

A common starting point is a Uniswap V2-style constant product AMM where the fee adjusts based on pool volatility. This example uses a simple moving average of trade size to adjust the fee between a minFee and maxFee.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract DynamicFeeAMM {
    uint256 public constant MIN_FEE = 3; // 0.03%
    uint256 public constant MAX_FEE = 50; // 0.5%
    uint256 public constant FEE_DENOMINATOR = 10000;
    
    uint256 public feeWindow = 100; // Number of blocks for moving average
    uint256[] public recentTradeSizes;
    uint256 public index;
    
    function swap(uint256 amountIn) external returns (uint256 amountOut) {
        // 1. Calculate dynamic fee based on recent volume
        uint256 currentFee = calculateDynamicFee();
        
        // 2. Apply fee to input amount
        uint256 feeAmount = (amountIn * currentFee) / FEE_DENOMINATOR;
        uint256 amountInAfterFee = amountIn - feeAmount;
        
        // 3. Execute constant product swap logic (simplified)
        // ... (x * y = k calculation here)
        
        // 4. Update volume tracker for next fee calculation
        recordTrade(amountIn);
    }
    
    function calculateDynamicFee() public view returns (uint256) {
        if (recentTradeSizes.length == 0) return MIN_FEE;
        
        uint256 avgVolume = getAverageVolume();
        // Higher volume -> lower fee (for liquidity incentive)
        // Simple linear interpolation between MIN_FEE and MAX_FEE
        uint256 fee = MAX_FEE - ((avgVolume * (MAX_FEE - MIN_FEE)) / (1e18));
        
        return fee < MIN_FEE ? MIN_FEE : fee;
    }
    
    function recordTrade(uint256 size) internal {
        // Circular buffer for moving average
        if (recentTradeSizes.length < feeWindow) {
            recentTradeSizes.push(size);
        } else {
            recentTradeSizes[index] = size;
            index = (index + 1) % feeWindow;
        }
    }
}

Key Mechanism: The fee decreases as the 100-block moving average of trade volume increases, incentivizing liquidity during high-usage periods. This mimics fee models used by DEXs like Trader Joe on Avalanche.

DYNAMIC FEE MODELS

Frequently Asked Questions

Common questions and technical clarifications for developers implementing dynamic fee mechanisms in DeFi protocols and smart contracts.

A dynamic fee model is a pricing mechanism where transaction costs (like swap fees or protocol commissions) automatically adjust based on real-time on-chain conditions, such as network congestion, pool utilization, or asset volatility. This contrasts with a static fee model, where the fee percentage is fixed and immutable after deployment.

Key differences:

  • Static Fees: Simple to implement (e.g., Uniswap V2's 0.3% swap fee) but cannot adapt to market stress or optimize for revenue/growth.
  • Dynamic Fees: Use oracles (like Chainlink) or internal metrics (like time-weighted average price - TWAP) to calculate fees. For example, a DEX might increase fees during high volatility to protect LPs from arbitrage losses, or a lending protocol might lower borrowing fees when utilization is low to attract users.

The core mechanism involves a smart contract function that calculates the fee using a predefined formula, often updated by governance or keepers.

conclusion
IMPLEMENTATION

Conclusion and Next Steps

This guide has outlined the core principles and components for designing a dynamic fee model. The next step is to implement and test your model in a live environment.

A well-designed dynamic fee model is a critical component for any protocol that manages congestion or incentivizes behavior. The key is to start with a clear objective—whether it's managing network load, optimizing liquidity provider returns, or balancing supply and demand. Your model should be transparent and verifiable on-chain, using clear data inputs like block.basefee, gasUsed, or a custom oracle feed. Avoid over-engineering; begin with a simple formula like a linear or exponential adjustment based on a single key metric, and iterate from there.

Before mainnet deployment, rigorous testing is non-negotiable. Use a forked mainnet environment with tools like Foundry or Hardhat to simulate real user activity and extreme market conditions. Stress-test your model's edge cases: what happens during a flash crash, a mempool spam attack, or a sudden surge in Total Value Locked (TVL)? Monitor for unintended consequences, such as fee volatility that discourages users or parameter settings that could be exploited for MEV. Consider implementing a time-weighted averaging mechanism for your input data to smooth out short-term spikes.

Your model will likely need adjustments. Plan for upgradeability and governance from the start. Use a transparent, time-locked process for parameter changes, potentially managed by a DAO or a multisig of trusted experts. Document every change and its rationale. For ongoing analysis, implement comprehensive logging and dashboards using services like The Graph or Dune Analytics to track key metrics: average fee paid, user retention, protocol revenue, and the model's impact on your core objective.

To explore these concepts further, review live implementations. Study how Uniswap V3 adjusts its swap fee tiers (0.05%, 0.30%, 1.00%) for different pool volatilities, or how the EIP-1559 base fee mechanism dynamically adjusts block space costs. The code for these systems is open-source and provides invaluable reference material. For a hands-on next step, fork a simple AMM or lending contract and implement a basic utilization-based fee to solidify your understanding.