|
| 1 | +# Gas markets |
| 2 | + |
| 3 | +In IPC, gas markets are algorithmic entities that determine key aspects of transaction pricing and dynamics within |
| 4 | +subnets. Starting from the axon-r06 release, subnets can freely customize their gas market, as long as they adhere to |
| 5 | +the standard actor interface defined below. This interface will evolve over time to accommodate new capabilities and |
| 6 | +features. |
| 7 | + |
| 8 | +## Capabilities |
| 9 | + |
| 10 | +Starting from the axon-r06 release, gas markets can update the base fee and the block gas limit. |
| 11 | + |
| 12 | +The **base fee** is applied during state transitions, and is used to calculate the network fee to execute a message |
| 13 | +per gas unit. This portion of the transaction fee is burnt by sending it to the f099 burn address within the subnet. |
| 14 | +Note that, today, these amounts remain at the f099 address in the subnet, and are counted towards the circulating |
| 15 | +supply of the subnet (as seen by the parent). In the future, we plan to physically burn these amounts in the subnet |
| 16 | +and notify the parent so that (a) the supply source is updated, and (b) these amounts are removed from the circulating |
| 17 | +supply accounting. |
| 18 | + |
| 19 | +The **block gas limit** is the maximum cumulative gas limit across all transactions in a block. This limit is enforced |
| 20 | +by the consensus layer, so updating it via the gas market actor will cause us to notify the consensus layer |
| 21 | +accordingly. |
| 22 | + |
| 23 | +## Gas market actor |
| 24 | + |
| 25 | +Gas markets are deployed as on-chain Wasm actors that implement a standard interface. The gas market is a singleton |
| 26 | +actor deployed at ID address f098 on the subnet. |
| 27 | + |
| 28 | +In axon-r06, the standard gas market interface is quite simple. It revolves around two interactions: |
| 29 | + |
| 30 | +1. Acquiring the current reading of the gas market. |
| 31 | +2. Updating the current utilization of the gas market (and returning the updated reading). |
| 32 | + |
| 33 | +The following Rust code defines the standard interface for gas markets. |
| 34 | + |
| 35 | +```rust |
| 36 | +/// A reading of the current gas market state for use by consensus. |
| 37 | +pub struct Reading { |
| 38 | + /// The current gas limit for the block. |
| 39 | + pub block_gas_limit: Gas, |
| 40 | + /// The current base fee for the block. |
| 41 | + pub base_fee: TokenAmount, |
| 42 | +} |
| 43 | + |
| 44 | +/// The current utilization for the client to report to the gas market. |
| 45 | +pub struct Utilization { |
| 46 | + /// The gas used by the current block, at the end of the block. To be invoked as an implicit |
| 47 | + /// message, so that gas metering for this message is disabled. |
| 48 | + pub block_gas_used: Gas, |
| 49 | +} |
| 50 | + |
| 51 | +/// The trait to be implemented by a gas market actor, provided here for convenience, |
| 52 | +/// using the standard Runtime libraries. Ready to be implemented as-is by an actor. |
| 53 | +pub trait GasMarket { |
| 54 | + /// Returns the current gas market reading. |
| 55 | + #[frc42(method_name = "CurrentReading")] |
| 56 | + fn current_reading(rt: &impl Runtime) -> Result<Reading, ActorError>; |
| 57 | + |
| 58 | + /// Updates the current utilization in the gas market, returning the reading after the update. |
| 59 | + #[frc42(method_name = "UpdateUtilization")] |
| 60 | + fn update_utilization( |
| 61 | + rt: &impl Runtime, |
| 62 | + utilization: Utilization, |
| 63 | + ) -> Result<Reading, ActorError>; |
| 64 | +} |
| 65 | +``` |
| 66 | + |
| 67 | +## Default gas market: EIP-1559 |
| 68 | + |
| 69 | +IPC ships with EIP-1559 as the default gas market, with constants identical to Filecoin mainnet's. |
| 70 | + |
| 71 | +Here are the constants, their roles in this algorithm, and their default values: |
| 72 | + |
| 73 | +| Constant | Description | Default value | |
| 74 | +|-----------------------------------|----------------------------------------------------------------------------------------------------|---------------| |
| 75 | +| `block_gas_limit` | The block gas limit, as defined above. | 10M (^) | |
| 76 | +| `minimal_base_fee` | The minimal base fee floor when gas utilization is low. | 100 atto | |
| 77 | +| `elasticity_multiplier` | Elasticity multiplier as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). | 2 | |
| 78 | +| `base_fee_max_change_denominator` | Base fee max change denominator as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). | 8 | |
| 79 | + |
| 80 | +(^) Matching the Filecoin block gas limit. As defined |
| 81 | +in [FIP-0032](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0032.md#gas-sizing-baseline), Filecoin sizes |
| 82 | +gas by adopting a baseline of 10 gas/nanosecond of wall-clock time, or 1 milligas/10 picosecond. This baseline follows |
| 83 | +from the need to sustain a 30s epoch by validating and applying unique messages in a tipset, with a block count |
| 84 | +following a Poisson distribution (win rate), with a 10B block gas limit, assuming 6s of block propagation time. Since |
| 85 | +IPC inherits the FVM, which encodes these assumptions, we keep the block gas limit equal. That said, it is worth to note |
| 86 | +some differences: (a) Tendermint consensus produces a single block per height, while Filecoin produces multiple blocks |
| 87 | +per epoch (usually oscillating between 4-10); (b) IPC subnets usually tick much faster than Filecoin (30s per epoch); |
| 88 | +(c) IPC is impacted by lower execution overhead than Lotus (Filecoin's reference client) as it doesn't need to traverse |
| 89 | +an FFI boundary to access the state store. |
| 90 | + |
| 91 | +### Setting the constants |
| 92 | + |
| 93 | +Developers can set the EIP-1559 constants through two mechanisms: |
| 94 | + |
| 95 | +1. At genesis, currently |
| 96 | + by [patching the initial state tree construction](https://github.com/consensus-shipyard/ipc/blob/702d49b619623915772fe935a86e59a89744c3b1/fendermint/vm/interpreter/src/genesis.rs#L443). |
| 97 | + In the near future we intend to provide an API to set these constants, so that forking and patching is no longer |
| 98 | + necessary. |
| 99 | +2. Updating the constants at runtime through an on-chain message. By default, this message can only be applied during an |
| 100 | + upgrade through the UpgradeScheduler, since the original implementation enforces the sender to be the system actor ( |
| 101 | + f00). However, developers can set a different authorized addressed, such as an EOA, a multisig, or a smart |
| 102 | + contracts (e.g. DAO, timelock, etc.) This requires patching the actor code. |
| 103 | + |
| 104 | +## Custom gas markets |
| 105 | + |
| 106 | +Developers can deploy a custom gas market by implementing the `GasMarket` trait in a Wasm actor, and replacing the |
| 107 | +default gas market at actor ID `f098`. This can be done at genesis, or in a network upgrade through the |
| 108 | +UpgradeScheduler. |
| 109 | + |
| 110 | +## Caveats |
| 111 | + |
| 112 | +1. Updating the block gas limit in a block containing other transactions leads to undefined behaviour. Always perform |
| 113 | + this update in isolation, and at the end of the block. The new block gas limit is applied from the next block |
| 114 | + onwards. |
0 commit comments