Durango Upgrade
Learn how to upgrade your Subnet-EVM and precompiles for the Durango network upgrade.
Durango will be activated on the Avalanche Mainnet at 11 AM ET (4 PM UTC) on Wednesday, March 6th, 2024. Subnet-EVM introduces a set of new features and backwards-incompatible changes with the Durango network upgrade. This guide will walk you through the process of upgrading your Subnet-EVM and precompiles for the Durango network upgrade.
The Durango network upgrade introduces new features and improvements to the Avalanche platform and Subnet-EVM. This guide will help you ensure that your Subnet-EVM and precompiles are compatible with the Durango network upgrade.
Note: Subnet-EVM already performs these upgrades in native stateful precompiles. This guide is for users who have custom precompiles and need to upgrade them for Durango.
Durango introduces following changes to Subnet-EVM:
- Avalanche Warp Messaging
- Events in Precompiles
- Manager Role
- Non-Strict Mode
- Shanghai Upgrade from ACP-24 will be activated with Durango without any further modification in Subnet-EVM.
Avalanche Warp Messaging
Avalanche Warp Messaging (AWM) is a new feature introduced with the Durango network upgrade. It enables native cross-Subnet communication and allows Virtual Machine (VM) developers to implement arbitrary communication protocols between any two Subnets. For more information about AWM see here.
Warp Precompile must be enabled for Subnets after Durango. For more information the precompile and activation see here
Events
Subnet-EVM Native Precompiles will start emitting events with the Durango network upgrade. This will allow you to listen to events emitted by Subnet-EVM native precompiles. Following events will be introduced:
event RoleSet(uint256 indexed role, address indexed account, address indexed sender, uint256 oldRole)
: This event will be emitted when a role is set for an account. Precompiles that usesIAllowList
interface will emit this event without requiring any changes. The event contains the role, account, sender as indexed parameters and old role as non-indexed parameter.event FeeConfigChanged(address indexed sender, FeeConfig oldFeeConfig, FeeConfig newFeeConfig)
: This event will be emitted when the fee configuration is changed inFeeManager
precompile. The event contains the sender as indexed parameter and old and new fee configuration as non-indexed parameters.event NativeCoinMinted(address indexed sender, address indexed recipient, uint256 amount)
: This event will be emitted when new native coins are minted. The event contains the sender, recipient as indexed parameters and the amount as non-indexed parameter.event RewardAddressChanged(address indexed sender, address indexed oldRewardAddress, address indexed newRewardAddress)
: This event will be emitted when the reward address is changed inRewardManager
precompile. The event contains the sender, old and new reward addresses as non-indexed parameters.event FeeRecipientsAllowed(address indexed sender)
: This event will be emitted when the fee recipients are allowed inRewardManager
precompile. The event contains the sender as indexed parameter.event RewardsDisabled(address indexed sender)
: This event will be emitted when the rewards are disabled inRewardManager
precompile. The event contains the sender as indexed parameter.
Custom Events
Events above are already introduced and handled in Subnet-EVM native precompiles. If you have a custom precompile, you can start emitting your custom events using Durango activation. In order to do this you can define your custom event in your solidity interface and regenerate the go bindings using precompilegen
tool, for more information see here.
Generally you will generate an event.go
file in addition to your existing precompile files. You need to implement how to emit your events and your events' gas costs, as in hello world example. In this guide we will use the hello world example to demonstrate how to emit custom events. The event that will be introduced is:
It will be emitted when the greeting is changed in the hello world precompile. You can find the hello world precompile here. We also assume that hello world precompile is already deployed before Durango and we will be upgrading it for Durango.
Adjusting Gas Costs
Adjusting gas costs for your custom events is very important. Emitted events are written to state and consume resources. You should make sure you're charging the right amount of gas before emitting your event.
precompilegen
tool automatically generates a scaffold for your gas calculations, however you should review and adjust the gas costs according to your needs, especially if you're using any arbitrary size data in your events.
Gas cost function for the event GreetingChanged(address indexed sender, string oldGreeting, string newGreeting)
looks like this:
We have charged the base gas cost, topics gas cost and data gas cost for the old and new greeting. Topic gas cost includes 2 topics, one for the signature hash of the event and the other for the indexed sender argument.
Data gas cost is calculated according to the data type and size. If you're not using any arbitrary size data in your events, you can define it as a constant.
Durango Activation Check
After completing defining your custom events, you need to pack your events, charge your event gas and emit them in your precompile functions. Since this procedure is non-backward compatible, you need to ensure that this will only be activated after the Durango network upgrade.
You can use the contract.IsDurangoActivated
function to check if the Durango network upgrade is activated. For Hello World example, we will be changing setGreeting
function starting here via following:
Note: this activation won't be needed if you plan to deploy your custom precompile after Durango.
Event Packers
Event packers and unpackers will be automatically generated with the precompilegen
tool. You can use these packers and unpackers to pack and unpack your custom events. For hello world example:
This will first charge gas for fetching the old greeting from the state fetch and then fetch it from the state. Then it will pack the event data with old and new greeting as non-indexed event data.
Emitting Events
After packing the event data, you can charge the event gas and emit your custom events using the stateDB.AddLog
function. For hello world example it starts here:
Manager Role
Durango introduces a new role called the manager role. The manager role is a mid-role between Admin
and Enabled
. The manager role is considered as an Enabled
account and perform restricted state-changing operations in precompiles. Manager role also can modify other Enabled
accounts. It can appoint new Enabled
accounts and remove existing Enabled
accounts. Manager role cannot modify other Manager
or Admin
accounts. For more information about AllowList see here.
If you have any precompile using AllowList, you can issue a call to setManager
in your precompile to appoint new Manager accounts. For upgrades or new precompiles with AllowList config you can use managerAddresses
as follow:
Non-Strict Mode
Strict mode unpacking prevents using extra padded bytes in inputs. This created some issue in few legacy contracts like Gnosis Multisig wallet. For more information about strict mode see solidity docs.
For Hello world example we were using this UnpackSetGreetingInput
with strict mode enabled before:
In order to handle extra padded bytes, Subnet-EVM will start using non-strict mode with Durango in Input Unpackers
. However since this change will be non-backward compatible you need to ensure that this will only be activated after the Durango network upgrade.
You can use the contract.IsDurangoActivated
function to check if the Durango network upgrade is activated. Now we will using this function to start using non-strict mode unpacking:
To call this function in setGreeting
we should use Durango activation as follows here:
This will ensure that non-strict mode unpacking is used after Durango activation.
This should not impose any critical issue for your custom precompiles. If you want to keep using the old strict mode and keep the backward compatibility you can use true
for the useStrictMode
parameter.
However if your precompile is mainly used from other deployed contracts (Solidity) you should do this transition in order to increase the compatibility of your precompile.
Last updated on