datahaven/operator/runtime/mainnet/src/precompiles.rs

161 lines
6.1 KiB
Rust
Raw Permalink Normal View History

// Copyright 2019-2025 The DataHaven Team
// This file is part of DataHaven.
// DataHaven is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// DataHaven is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with DataHaven. If not, see <http://www.gnu.org/licenses/>.
use crate::configs::MaxAdditionalFields;
use crate::governance::councils::{TechnicalCommitteeInstance, TreasuryCouncilInstance};
use crate::governance::custom_origins::Origin;
feat: Add ERC20 Balances precompile (#150) ## Summary - Introduces an ERC20-compatible precompile backed by `pallet_balances`, including approvals and EIP-2612 permit. - Wires the precompile into Mainnet, Testnet, and Stagenet at address `0x0000000000000000000000000000000000000802` (u64: 2050). - Adds comprehensive unit tests and a mock runtime. ## Motivation - Allow EVM contracts and tooling to interact with Substrate balances via a familiar ERC20 interface. - Support off-chain approvals via EIP-2612 for gasless approvals and improved UX. ## Key Changes - New crate: `operator/precompiles/erc20-balances` - Core logic: `src/lib.rs` - EIP-2612 helpers and validation: `src/eip2612.rs` - Tests + mock runtime: `src/tests.rs`, `src/mock.rs` - Runtime wiring (all networks): add `Erc20BalancesPrecompile` at `AddressU64<2050>` - `operator/runtime/{mainnet,stagenet,testnet}/src/precompiles.rs` - Workspace plumbing: include `pallet-evm-precompile-balances-erc20` in `operator/Cargo.toml` ## Interface - ERC20: `totalSupply`, `balanceOf`, `allowance`, `approve`, `transfer`, `transferFrom`, `name`, `symbol`, `decimals` - Native-only flows: `deposit()` (fallback/payable) and `withdraw(uint256)` - EIP-2612: `permit(owner,spender,value,deadline,v,r,s)`, `nonces(owner)`, `DOMAIN_SEPARATOR()` - Events: `Transfer`, `Approval`, `Deposit`, `Withdrawal` - Storage: - Approvals via `ApprovesStorage` (double map: owner → spender → amount) - EIP-2612 nonces via `NoncesStorage` keyed by `H160` - Instance-aware prefixes to support multiple `pallet_balances` instances
2025-09-12 08:57:44 +00:00
use pallet_evm_precompile_balances_erc20::{Erc20BalancesPrecompile, Erc20Metadata};
use pallet_evm_precompile_batch::BatchPrecompile;
use pallet_evm_precompile_blake2::Blake2F;
use pallet_evm_precompile_bn128::{Bn128Add, Bn128Mul, Bn128Pairing};
use pallet_evm_precompile_call_permit::CallPermitPrecompile;
use pallet_evm_precompile_collective::CollectivePrecompile;
use pallet_evm_precompile_conviction_voting::ConvictionVotingPrecompile;
use pallet_evm_precompile_file_system::FileSystemPrecompile;
use pallet_evm_precompile_identity::IdentityPrecompile;
use pallet_evm_precompile_modexp::Modexp;
use pallet_evm_precompile_preimage::PreimagePrecompile;
2025-09-12 07:45:26 +00:00
use pallet_evm_precompile_proxy::{OnlyIsProxyAndProxy, ProxyPrecompile};
use pallet_evm_precompile_referenda::ReferendaPrecompile;
use pallet_evm_precompile_registry::PrecompileRegistry;
use pallet_evm_precompile_sha3fips::Sha3FIPS256;
use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256};
use precompile_utils::precompile_set::*;
type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile);
feat: Add ERC20 Balances precompile (#150) ## Summary - Introduces an ERC20-compatible precompile backed by `pallet_balances`, including approvals and EIP-2612 permit. - Wires the precompile into Mainnet, Testnet, and Stagenet at address `0x0000000000000000000000000000000000000802` (u64: 2050). - Adds comprehensive unit tests and a mock runtime. ## Motivation - Allow EVM contracts and tooling to interact with Substrate balances via a familiar ERC20 interface. - Support off-chain approvals via EIP-2612 for gasless approvals and improved UX. ## Key Changes - New crate: `operator/precompiles/erc20-balances` - Core logic: `src/lib.rs` - EIP-2612 helpers and validation: `src/eip2612.rs` - Tests + mock runtime: `src/tests.rs`, `src/mock.rs` - Runtime wiring (all networks): add `Erc20BalancesPrecompile` at `AddressU64<2050>` - `operator/runtime/{mainnet,stagenet,testnet}/src/precompiles.rs` - Workspace plumbing: include `pallet-evm-precompile-balances-erc20` in `operator/Cargo.toml` ## Interface - ERC20: `totalSupply`, `balanceOf`, `allowance`, `approve`, `transfer`, `transferFrom`, `name`, `symbol`, `decimals` - Native-only flows: `deposit()` (fallback/payable) and `withdraw(uint256)` - EIP-2612: `permit(owner,spender,value,deadline,v,r,s)`, `nonces(owner)`, `DOMAIN_SEPARATOR()` - Events: `Transfer`, `Approval`, `Deposit`, `Withdrawal` - Storage: - Approvals via `ApprovesStorage` (double map: owner → spender → amount) - EIP-2612 nonces via `NoncesStorage` keyed by `H160` - Instance-aware prefixes to support multiple `pallet_balances` instances
2025-09-12 08:57:44 +00:00
pub struct NativeErc20Metadata;
impl Erc20Metadata for NativeErc20Metadata {
fn name() -> &'static str {
"HAVE"
}
fn symbol() -> &'static str {
"HAVE"
}
fn decimals() -> u8 {
18
}
fn is_native_currency() -> bool {
true
}
}
/// EVM precompiles available in the DataHaven Mainnet runtime.
#[precompile_utils::precompile_name_from_address]
type DataHavenPrecompilesAt<R> = (
// Ethereum precompiles:
// We allow DELEGATECALL to stay compliant with Ethereum behavior.
PrecompileAt<AddressU64<1>, ECRecover, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<2>, Sha256, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<3>, Ripemd160, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<4>, Identity, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<5>, Modexp, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<6>, Bn128Add, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<7>, Bn128Mul, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<8>, Bn128Pairing, EthereumPrecompilesChecks>,
PrecompileAt<AddressU64<9>, Blake2F, EthereumPrecompilesChecks>,
// Non-DataHaven specific nor Ethereum precompiles :
PrecompileAt<AddressU64<1024>, Sha3FIPS256, (CallableByContract, CallableByPrecompile)>,
RemovedPrecompileAt<AddressU64<1025>>,
PrecompileAt<AddressU64<1026>, ECRecoverPublicKey, (CallableByContract, CallableByPrecompile)>,
RemovedPrecompileAt<AddressU64<1027>>,
// DataHaven specific precompiles:
feat: Add ERC20 Balances precompile (#150) ## Summary - Introduces an ERC20-compatible precompile backed by `pallet_balances`, including approvals and EIP-2612 permit. - Wires the precompile into Mainnet, Testnet, and Stagenet at address `0x0000000000000000000000000000000000000802` (u64: 2050). - Adds comprehensive unit tests and a mock runtime. ## Motivation - Allow EVM contracts and tooling to interact with Substrate balances via a familiar ERC20 interface. - Support off-chain approvals via EIP-2612 for gasless approvals and improved UX. ## Key Changes - New crate: `operator/precompiles/erc20-balances` - Core logic: `src/lib.rs` - EIP-2612 helpers and validation: `src/eip2612.rs` - Tests + mock runtime: `src/tests.rs`, `src/mock.rs` - Runtime wiring (all networks): add `Erc20BalancesPrecompile` at `AddressU64<2050>` - `operator/runtime/{mainnet,stagenet,testnet}/src/precompiles.rs` - Workspace plumbing: include `pallet-evm-precompile-balances-erc20` in `operator/Cargo.toml` ## Interface - ERC20: `totalSupply`, `balanceOf`, `allowance`, `approve`, `transfer`, `transferFrom`, `name`, `symbol`, `decimals` - Native-only flows: `deposit()` (fallback/payable) and `withdraw(uint256)` - EIP-2612: `permit(owner,spender,value,deadline,v,r,s)`, `nonces(owner)`, `DOMAIN_SEPARATOR()` - Events: `Transfer`, `Approval`, `Deposit`, `Withdrawal` - Storage: - Approvals via `ApprovesStorage` (double map: owner → spender → amount) - EIP-2612 nonces via `NoncesStorage` keyed by `H160` - Instance-aware prefixes to support multiple `pallet_balances` instances
2025-09-12 08:57:44 +00:00
PrecompileAt<
AddressU64<2050>,
Erc20BalancesPrecompile<R, NativeErc20Metadata>,
(CallableByContract, CallableByPrecompile),
>,
PrecompileAt<
AddressU64<2056>,
BatchPrecompile<R>,
(
SubcallWithMaxNesting<2>,
// Batch is the only precompile allowed to call Batch.
CallableByPrecompile<OnlyFrom<AddressU64<2056>>>,
),
>,
PrecompileAt<
AddressU64<2058>,
CallPermitPrecompile<R>,
(SubcallWithMaxNesting<0>, CallableByContract),
>,
2025-09-12 07:45:26 +00:00
PrecompileAt<
AddressU64<2059>,
ProxyPrecompile<R>,
(
CallableByContract<OnlyIsProxyAndProxy<R>>,
SubcallWithMaxNesting<0>,
// Batch is the only precompile allowed to call Proxy.
CallableByPrecompile<OnlyFrom<AddressU64<2056>>>,
),
>,
PrecompileAt<
AddressU64<2064>,
CollectivePrecompile<R, TreasuryCouncilInstance>,
(CallableByContract, CallableByPrecompile),
>,
PrecompileAt<
AddressU64<2065>,
ReferendaPrecompile<R, Origin>,
(CallableByContract, CallableByPrecompile),
>,
PrecompileAt<
AddressU64<2066>,
ConvictionVotingPrecompile<R>,
(CallableByContract, CallableByPrecompile),
>,
PrecompileAt<
AddressU64<2067>,
PreimagePrecompile<R>,
(CallableByContract, CallableByPrecompile),
>,
PrecompileAt<
AddressU64<2068>,
CollectivePrecompile<R, TechnicalCommitteeInstance>,
(CallableByContract, CallableByPrecompile),
2025-09-12 07:45:26 +00:00
>,
PrecompileAt<
AddressU64<2069>,
PrecompileRegistry<R>,
(CallableByContract, CallableByPrecompile),
>,
PrecompileAt<
AddressU64<2072>,
IdentityPrecompile<R, MaxAdditionalFields>,
(CallableByContract, CallableByPrecompile),
>,
PrecompileAt<AddressU64<1028>, FileSystemPrecompile<R>>,
);
/// The PrecompileSet installed in the DataHaven runtime.
/// We include the nine Istanbul precompiles
/// (https://github.com/ethereum/go-ethereum/blob/3c46f557/core/vm/contracts.go#L69)
/// The following distribution has been decided for the precompiles
/// 0-1023: Ethereum Mainnet Precompiles
/// 1024-2047 Precompiles that are not in Ethereum Mainnet but are neither DataHaven specific
/// 2048-4095 DataHaven specific precompiles
pub type DataHavenPrecompiles<R> = PrecompileSetBuilder<
R,
(
// Skip precompiles if out of range.
PrecompilesInRangeInclusive<(AddressU64<1>, AddressU64<4095>), DataHavenPrecompilesAt<R>>,
),
>;