RewardManager Precompile

Learn how to use the RewardManager Precompile on your Avalanche L1 blockchain.

Overview

Fee reward mechanism can be configured with this stateful precompile contract called as RewardManager. Configuration can include burning fees, sending fees to a predefined address, or enabling fees to be collected by block producers.

Activating the Precompile

This precompile can be configured as follows in the genesis file:

{
  "config": {
    "rewardManagerConfig": {
      "blockTimestamp": 0,
      "adminAddresses": ["0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"]
    }
  }
}

adminAddresses denotes admin accounts who can add other Admin or Enabled accounts. Admin, Manager and Enabled are both eligible to change the current fee mechanism.

Interface and Address

The RewardManager precompile is located at address 0x0200000000000000000000000000000000000004 and implements the following interface:

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
interface IRewardManager {
  // RewardAddressChanged is the event logged whenever reward address is modified
  event RewardAddressChanged(
    address indexed sender,
    address indexed oldRewardAddress,
    address indexed newRewardAddress
  );
 
  // FeeRecipientsAllowed is the event logged whenever fee recipient is modified
  event FeeRecipientsAllowed(address indexed sender);
 
  // RewardsDisabled is the event logged whenever rewards are disabled
  event RewardsDisabled(address indexed sender);
 
  // setRewardAddress sets the reward address to the given address
  function setRewardAddress(address addr) external;
 
  // allowFeeRecipients allows block builders to claim fees
  function allowFeeRecipients() external;
 
  // disableRewards disables block rewards and starts burning fees
  function disableRewards() external;
 
  // currentRewardAddress returns the current reward address
  function currentRewardAddress() external view returns (address rewardAddress);
 
  // areFeeRecipientsAllowed returns true if fee recipients are allowed
  function areFeeRecipientsAllowed() external view returns (bool isAllowed);
  
  // IAllowList
  event RoleSet(uint256 indexed role, address indexed account, address indexed sender, uint256 oldRole);
 
  // Set [addr] to have the admin role over the precompile contract.
  function setAdmin(address addr) external;
 
  // Set [addr] to be enabled on the precompile contract.
  function setEnabled(address addr) external;
 
  // Set [addr] to have the manager role over the precompile contract.
  function setManager(address addr) external;
 
  // Set [addr] to have no role for the precompile contract.
  function setNone(address addr) external;
 
  // Read the status of [addr].
  function readAllowList(address addr) external view returns (uint256 role);
}

The RewardManager precompile uses the AllowList interface to restrict access to its functionality.

Implementation

You can find the implementation of the RewardManager precompile in the subnet-evm repository.

Capabilities

In addition to the AllowList interface, the RewardManager adds the following capabilities:

  • setRewardAddress: sets the address to which fees are sent. This address can be a contract or a user address. The address becomes the required coinbase address for the blocks that this mechanism is enabled on. Meaning that it will receive the fees collected from the transactions in the block. Receiving fees will not call any contract functions or fallback functions. It will simply increase the balance of the address by the amount of fees.
  • allowFeeRecipients: enables block producers to claim fees. This will allow block producers to claim fees by specifying their own addresses in their chain configs.
  • disableRewards: disables block rewards and starts burning fees.
  • currentRewardAddress: returns the current reward address. This is the address to which fees are sent. It can include black hole address (0x010...0) which means that fees are burned. It can also include a predefined hash (0x0000000000000000000000000000000000000000) denoting custom fee recipients are allowed. It's advised to use the areFeeRecipientsAllowed function to check if custom fee recipients are allowed first.
  • areFeeRecipientsAllowed: returns true if custom fee recipients are allowed.
  • RewardAddressChanged: an event that is emitted when the reward address is updated. Topics include the sender, the old reward address, and the new reward address.
  • FeeRecipientsAllowed: an event that is emitted when fee recipients are allowed. Topics include the sender.
  • RewardsDisabled: an event that is emitted when rewards are disabled. Topics include the sender.

These 3 mechanisms (burning, sending to a predefined address, and enabling fees to be collected by block producers) cannot be enabled at the same time. Enabling one mechanism will take over the previous mechanism. For example, if you enable allowFeeRecipients and then enable disableRewards, the disableRewards will take over and fees will be burned.

Note that reward addresses or fee recipient addresses are not required to be an admin or enabled account.

Initial Configuration

It's possible to enable this precompile with an initial configuration to activate its effect on activation timestamp. This provides a way to enable the precompile without an admin address to change the fee reward mechanism. This can be useful for networks that require a one-time reward mechanism change without specifying any admin addresses.

Without this initial configuration, the precompile will inherit the feeRecipients mechanism activated at genesis. Meaning that if allowFeeRecipients is set to true in the genesis file, the precompile will be enabled with the allowFeeRecipients mechanism. Otherwise it will keep burning fees. To use the initial configuration, you need to specify the initial reward mechanism in initialRewardConfig field in your genesis or upgrade file.

Allow Custom Fee Recipients

In order to allow custom fee recipients, you need to specify the allowFeeRecipients field in the initialRewardConfig:

{
  "rewardManagerConfig": {
    "blockTimestamp": 0,
    "initialRewardConfig": {
      "allowFeeRecipients": true
    }
  }
}

Set a Reward Address

In order to set an address to receive all transaction rewards, you need to specify the rewardAddress field in the initialRewardConfig:

{
  "rewardManagerConfig": {
    "blockTimestamp": 0,
    "initialRewardConfig": {
      "rewardAddress": "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
    }
  }
}

Disable Rewards

In order to disable rewards and start burning fees, you need to leave all fields in the initialRewardConfig empty:

{
  "rewardManagerConfig": {
    "blockTimestamp": 0,
    "initialRewardConfig": {}
  }
}

However this is different than the default behavior of the precompile. If you don't specify the initialRewardConfig field, the precompile will inherit the feeRecipients mechanism activated at genesis. Meaning that if allowFeeRecipients is set to true in the genesis file, the precompile will be enabled with the allowFeeRecipients mechanism. Otherwise it will keep burning fees. Example configuration for this case:

{
  "rewardManagerConfig": {
    "blockTimestamp": 0,
    "adminAddresses": ["0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"]
  }
}

If allowFeeRecipients and rewardAddress are both specified in the initialRewardConfig field then an error will be returned and precompile won't be activated.

Is this guide helpful?

On this page