Skip to main content

Designing an Effective Blockchain Fee Mechanism: A Case Study of Moonbeam

In the dynamic world of blockchain technology, the intricate design of fee mechanisms plays a pivotal role in aligning the interests of network operators with those of participants. Blockchains bring together the operators of a network with those who want to participate in the network, allowing one to provide services to the other. These services can vary, but they almost always include basic transaction inclusion and ordering, also known as block production. Providing this service incurs an operating cost, so it is natural to collect a fee for doing so.

There are many ways that a fee can be collected, allowing for a broad design space. Additionally, fees can be realized by operators in different ways. The most straightforward mechanism is to transfer the fee to the operator, allowing them to accumulate capital. Operators can also see an increase in value in less straightforward ways such as through burning the fee (reducing supply) or paying the fee to a treasury (which presumably spends it in constructive ways).

A well-designed fee mechanism will use this design space to optimize a fee for all participants. This maximizes value, reduces friction, and removes opportunities for abuse while ensuring operators have a strong incentive to perform their duties.

In this context, the case of Moonbeam presents a fascinating study. Moonbeam has explored this design space and taken opportunities to fine-tune its fee mechanism to match its unique characteristics and challenges. This article will explore how Moonbeam managed to reconcile two very different fee mechanisms in a nearly seamless way, offering valuable lessons in the design process for an efficient blockchain fee mechanism. 

Understanding Blockchain Fee Mechanisms

Before we delve deeper, let’s first establish a firm understanding of blockchain fee mechanisms and the necessary terms, providing a solid foundation to comprehend the nuances of designing and implementing effective fee mechanisms.

Bidding Systems: Perhaps the simplest way to implement a fee pricing mechanism is to let users bid on the price they’re willing to pay, similar to an open-market bidding system. Transactions are then prioritized by highest fee, meaning transactions with higher fees usually get included first. While simple, it leads to volatility. 

Algorithmically-Controlled Fees: A popular alternative to bidding systems is to let the protocol itself control the fee pricing through some algorithm. Typically this helps achieve predictability and reduce volatility while still responding to demand. It is important to design these effectively, however; since there is no human at the wheel, this can lead to impractical fee prices.

Fee Handling: There are big differences in how fees are handled as well. Fees can be directly paid to block authors (immediately or in the future). They can be paid to some other party like a community treasury. They can also be burned, which does exactly what it sounds like – tokens are permanently destroyed, which indirectly helps all token holders by reducing supply. These techniques can also be mixed in various ways to achieve different goals.

General Terms 

Transaction: A message from a user expressing what they want to be done, such as sending money to another person. Messages are signed by the user and usually specify a fee that can be paid for including them.

Fee: A cost incurred for receiving a service such as having a transaction included in a block.

Tip: An amount beyond the fee to be paid for service. Sometimes a fee and a tip are the same thing.

Burn: Erasing tokens from existence. This is sometimes done with a fee as an alternative to paying it out to another party. It has the effect of reducing supply, which in turn improves value.

Congestion: Only so many transactions can fit in a block. When there are more transactions over time than can be processed, we say there is high congestion. Another way to think of this is as demand for block space.

Volatility: Rapid increases or decreases in price. A bidding-based fee mechanism often results in high volatility as users speculate on short term price changes.

Txpool: A transaction pool or “txpool” is the pool of transactions which have not yet been included in a block and can be included in the future.

Prioritization: Transactions in a txpool must be prioritized in some way so that they are included in an optimal way, usually preferring to maximize profits from fees or tips.

Moonbeam’s Fee Mechanism: A Deep Dive

Moonbeam is both a fully-EVM compatible blockchain and a Polkadot parachain. This means a lot of things: it runs Ethereum smart contracts with little or no modifications, it supports Polkadot’s XCM in order to transact and bridge with other parachains, and it has state-of-the-art features like Gov2. It even makes most of this extra functionality available to the EVM via precompiles for smart contracts to leverage.

One consequence of this duality is that it supports two transaction protocols: one based on Ethereum and the other on Substrate (the framework on which Polkadot blockchains are built). Most users only need to use Ethereum transactions, but the existence of two still causes conflicts with pricing and fairness.

At best, this problem is merely confusing to users because their fees may be drastically different in one case than the other. The distinction between types may be vague to a user, so if they see that one operation is extremely cheap but another is very expensive, they will not know what to expect. At its worst, it can cause undesirable incentives and can create problems when prioritizing transactions of mixed-types from the txpool. For example, without accounting for the discrepancy in the txpool prioritization mechanism, it is likely that all Substrate transactions will take precedence over all Ethereum transactions (or vise-versa). This is obviously a bad UX, but can even allow for an attacker to censor one transaction type by spamming the other.

Transaction Types on Moonbeam

In order to understand the challenge of reconciling these two transaction types, we will take a closer look at each.

Ethereum Transactions

Moonbeam implements standard Ethereum transactions, utilizing EIP-1559 as the fee mechanism. As a reminder, this blockchain fee mechanism works as follows:

  • Each opcode executed in the EVM incurs a cost, known as its gas cost. A transaction specifies how much gas it’s willing to pay for, as well as the maximum price it’s willing to pay per-gas.
  • For a transaction to be valid, its sending account must be able to pay for the maximum fee-per-gas multiplied by the maximum gas it has specified. Even though this amount is usually far more than the actual cost, this ensures that it can cover its worst-case scenario.

Each Ethereum block algorithmically determines a per-gas fee, called the `base_fee`. This is the actual fee (plus a potential per-gas tip) that is actually paid. This fee adjusts up and down based on how full the previous block was. We call this a congestion-based fee calculation. More info on this algorithm can be found here.

Fee:

Substrate Transactions

Substrate transactions are also supported by Moonbeam. These transactions rely on Substrate’s transaction-payment pallet for their pricing/fee mechanism. It has a lot more moving pieces than Ethereum transactions. It works as follows:

  • Transactions specify a particular function to call, and that function’s cost is known in advance. There is no notion of gas built into the fee mechanism. However, the function’s pricing can scale on factors such as the number of users it must iterate over.
  • As a result, these transactions usually have a precise fee to charge. Like Ethereum transactions, this is charged up-front, although they can refund some of the fee afterwards.
  • As with Ethereum and EIP-1559, transaction-payment has an algorithmic fee that is adjusted based on congestion once per block. Its floating fee is only one of several multipliers, however, and has less influence on the overall fee a user would pay than Ethereum’s `base-fee`.
  • The fee multiplier allows for upper and lower bounds to be set, preventing it from drifting endlessly up or down.

Fee:

Property Ethereum Substrate
Pricing Granularity Opcode Entire function call
Fee Estimate Overestimated Precise
Excess Fee Refunded? Yes Optional
Fee Multiplier Scaling Linear per gas used Complicated
Fee Multiplier Min/Max None Optional
Algorithmic Fee Fixed, EIP-1559 Tunable
Tips Supported Yes, but may not apply depending on base-fee Yes, flat tip

Correlating Fee Prices

As stated above, we wish to glue these two blockchain fee mechanisms together so that their relative expense to a user is similar at any point in time. One way to accomplish this is to use one fee multiplier for both cases. They’re different units of measure, but we can include a scalar to handle this.

It’s more complicated than this, however, because the two fee multipliers affect their fee structure differently. In Ethereum, the `base_fee` scales the entire cost of the transaction linearly, since the entire transaction’s cost is first expressed in terms of gas and then multiplied by the `base_fee`. `transaction-payment` only applies its multiplier to one small part of its overall fee structure: the `weight` of the resources it uses.

Furthermore, some transaction costs are dominated by this resource weight fee while others are virtually non impacted by it, depending on what the transaction’s function call actually does. It may still be possible to use the “gluing” approach, but it would only have the desired effect within some narrow range.

Which Mechanism to Use

With Moonbeam being Ethereum-focused, it would make sense to adopt EIP-1559’s fee mechanism and translate it to work with Substrate-based transactions rather than the other way around. This would maximize Ethereum compatibility.

However, a close look at EIP-1559’s congestion algorithm suggests that it fundamentally relies on a feedback loop in order to stabilize. A decrease in congestion leads to a decrease in fees, which encourages more transaction volume as users take advantage of lower fees. The inverse of this feedback mechanism is true as well, and these two forces act to stabilize fees according to demand for transaction inclusion.

Source: https://forum.moonbeam.network/t/proposal-dynamic-fee-mechanism-for-moonbeam-and-moonriver/241

Moonbeam, being a relatively new network, did not have this robust feedback mechanism ready to kick in at the time that this fee translation work was done, leading us to believe that the congestion modifier would drift indefinitely in one direction or another. Since transaction-payment had many different parameters which could be configured, it felt like a much safer and more flexible choice.

Bounding

We know that we need to bound this fee multiplier to some range where the two transaction types do not diverge too much, acknowledging that the multipliers will affect some transactions more than others.

The approach we used for this problem was to simulate transactions given various extreme use-cases using different multiplier conversion algorithms in order to see how we could best maximize a useful range of usable values. Once we identified an algorithm that worked well, we then used the min/max bounds from `transaction-payment` to confine the multiplier to a suitable range.

Conclusion

Moonbeam’s unique composition as being simultaneously compatible with Ethereum, EVM, and Substrate created design challenges for handling transaction fees. Compatibility for Moonbeam has always been of utmost importance, so a solution was required that worked with all existing user tools and avoided creating surprises for end-users.

We ultimately chose to adjust the fee multiplier used in Substrate transactions to work as an Ethereum base-fee, but this created some secondhand problems related to how the fee impacts the two transaction prices as well as how the two transactions could be prioritized fairly.

Substrate’s flexibility in its congestion-based fee algorithm allowed us to tune this so that these problems were acceptably bounded. This has worked well so far, although the solution may be somewhat “overfitted.” When compared to EIP-1559 or Substrate’s transaction-payment pallet (or the free-market bidding mechanism of ages past), Moonbeam’s design seems somewhat rigid. However, it has served its purpose well and has produced a fee which remains practical under real-world conditions.

For teams looking to adapt a blockchain fee mechanism to their own needs while maintaining compatibility with existing standards, I recommend first identifying which aspects of the existing mechanism(s) can be modified without sacrificing compatibility. Then, understand how these aspects can be tuned to meet your needs. Proceed with some modeling, understand what your extreme cases are, and be prepared to iterate once you have studied your results in practical scenarios.