Precompile to check active precompiles
Hi, I’m Jérémy (nanocryk on GitHub) of the PureStake dev team. I focus mainly on features related to the EVM, including the precompiles.
Summary
This is a proposal to add a new EVM Precompile allowing checking which precompiles are available and detecting when precompiles are phased-out.
Abstract
EVM precompiles allow extending the features of the EVM by having contracts not defined using EVM bytecode but directly in the node code, or in the case of Moonbeam in the Runtime. Ethereum mainet have precompiles only for cryptographic primitives that would be too costly or impossible to perform in bytecode. Moonbeam, being a Substrate-based chain, adds more precompiles allowing interactions with the Substrate world. This means that with the Substrate and Polkadot ecosystem evolving some features will necessarily evolve in backward-incompatible ways, such as the change for Gov1 to Gov2 or future changes in XCM.
The solution proposed is a precompile which allows checking if a given precompile is still supported or not, which can be used by smart contracts to provide an exit strategy to users when a necessary precompile is removed.
New precompile
A new precompile would be introduced with a function isActivePrecompile(address) returns bool
that would return true
if the address is part of the Runtime PrecompileSet, and false
otherwise (for removed precompiles and for non precompiles).
Precompile removal
A precompile would be removed if the functionality it exposes is no longer available in the Runtime. For exemple as Gov1 is progressively being phased-out in favor of Gov2, once Gov1 is entirely removed the current Gov1 Democracy precompile will no longer be able to work, and it is unlikely to make it work with Gov2 without breaking-changes that would affect contracts.
In that case the precompile will be removed and replaced with code that always reverts, and isActivePrecompile
will now return false
while it returned true
before. The precompile for Gov2 would be deployed on a different address for new contracts to use it.
Impact for smart contract developers
The introduction of this precompile is not in itself a breaking change. Currently deployed contracts are not affected. Newly deployed contracts however should use this new precompile to allow its users to have a clear exit path in case the precompile the contract is relying on is removed, without the need for an admin to intervein. Contracts implemented with the proxy design can update their implementation to allow the same thing.
Here is an exemple of how to use this precompile:
interface IActivePrecompiles {
function isActivePrecompile(address precompileAddress)
external view returns (bool);
}
interface IDemocracy {
function second(uint256 propIndex, uint256 secondsUpperBound) external;
}
contract Exemple {
IActivePrecompiles constant ACTIVE_PRECOMPILES = IActivePrecompiles(/* TODO: Address*/);
IDemocracy constant DEMOCRACY = IDemocracy(0x0000000000000000000000000000000000000803);
bool public enabled = true;
modifier isEnabled() {
require(enabled, "Contract is now disabled");
_;
}
modifier isDisabled() {
require(!enabled, "Contract is not disabled");
_;
}
function someFunction() isEnabled() external {
// do stuff with the precompile.
// this will revert if Democracy precompile is removed.
DEMOCRACY.second(1, 1);
}
function exitPath() isDisabled() external {
// Do something only allowed if the contract has been disabled following
// precompile removal.
}
function disable() external {
bool active = ACTIVE_PRECOMPILES.isActivePrecompile(address(DEMOCRACY));
if (!active) {
enabled = false;
}
}
}
Next steps
After a few days of collecting feedback from the Community and if there are arguments against/or new suggestions, a 7 days voting session will take place. Otherwise this idea will be implemented and proposed to be included in one of the following Runtime Upgrades.
If you have any questions or comments, feel free to reply in the comment section below.