Skip to content

Commit ecf7f52

Browse files
authored
Merge pull request #1131 from opentensor/feat/sudo_toggle_evm_precompile
extrinsic to enable disable precompile
2 parents a819d77 + e0e8aab commit ecf7f52

File tree

4 files changed

+194
-7
lines changed

4 files changed

+194
-7
lines changed

pallets/admin-utils/src/lib.rs

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ mod tests;
2323
#[frame_support::pallet]
2424
pub mod pallet {
2525
use super::*;
26-
use frame_support::dispatch::DispatchResult;
2726
use frame_support::pallet_prelude::*;
2827
use frame_support::traits::tokens::Balance;
28+
use frame_support::{dispatch::DispatchResult, pallet_prelude::StorageMap};
2929
use frame_system::pallet_prelude::*;
3030
use pallet_evm_chain_id::{self, ChainId};
3131
use sp_runtime::BoundedVec;
@@ -69,7 +69,16 @@ pub mod pallet {
6969
}
7070

7171
#[pallet::event]
72-
pub enum Event<T: Config> {}
72+
#[pallet::generate_deposit(pub(super) fn deposit_event)]
73+
pub enum Event<T: Config> {
74+
/// Event emitted when a precompile operation is updated.
75+
PrecompileUpdated {
76+
/// The type of precompile operation being updated.
77+
precompile_id: PrecompileEnum,
78+
/// Indicates if the precompile operation is enabled or not.
79+
enabled: bool,
80+
},
81+
}
7382

7483
// Errors inform users that something went wrong.
7584
#[pallet::error]
@@ -81,6 +90,37 @@ pub mod pallet {
8190
/// The maximum number of subnet validators must be more than the current number of UIDs already in the subnet.
8291
MaxAllowedUIdsLessThanCurrentUIds,
8392
}
93+
/// Enum for specifying the type of precompile operation.
94+
#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, Debug, Copy)]
95+
pub enum PrecompileEnum {
96+
/// Enum for balance transfer precompile
97+
BalanceTransfer,
98+
/// Enum for staking precompile
99+
Staking,
100+
/// Enum for subnet precompile
101+
Subnet,
102+
/// Enum for metagraph precompile
103+
Metagraph,
104+
/// Enum for neuron precompile
105+
Neuron,
106+
}
107+
108+
#[pallet::type_value]
109+
/// Default value for precompile enable
110+
pub fn DefaultPrecompileEnabled<T: Config>() -> bool {
111+
true
112+
}
113+
114+
#[pallet::storage]
115+
/// Map PrecompileEnum --> enabled
116+
pub type PrecompileEnable<T: Config> = StorageMap<
117+
_,
118+
Blake2_128Concat,
119+
PrecompileEnum,
120+
bool,
121+
ValueQuery,
122+
DefaultPrecompileEnabled<T>,
123+
>;
84124

85125
/// Dispatchable functions allows users to interact with the pallet and invoke state changes.
86126
#[pallet::call]
@@ -1307,6 +1347,36 @@ pub mod pallet {
13071347
pallet_subtensor::Pallet::<T>::ensure_subnet_owner_or_root(origin, netuid)?;
13081348
pallet_subtensor::Pallet::<T>::toggle_transfer(netuid, toggle)
13091349
}
1350+
1351+
/// Toggles the enablement of an EVM precompile.
1352+
///
1353+
/// # Arguments
1354+
/// * `origin` - The origin of the call, which must be the root account.
1355+
/// * `precompile_id` - The identifier of the EVM precompile to toggle.
1356+
/// * `enabled` - The new enablement state of the precompile.
1357+
///
1358+
/// # Errors
1359+
/// * `BadOrigin` - If the caller is not the root account.
1360+
///
1361+
/// # Weight
1362+
/// Weight is handled by the `#[pallet::weight]` attribute.
1363+
#[pallet::call_index(62)]
1364+
#[pallet::weight((0, DispatchClass::Operational, Pays::No))]
1365+
pub fn sudo_toggle_evm_precompile(
1366+
origin: OriginFor<T>,
1367+
precompile_id: PrecompileEnum,
1368+
enabled: bool,
1369+
) -> DispatchResult {
1370+
ensure_root(origin)?;
1371+
if PrecompileEnable::<T>::get(precompile_id) != enabled {
1372+
PrecompileEnable::<T>::insert(precompile_id, enabled);
1373+
Self::deposit_event(Event::PrecompileUpdated {
1374+
precompile_id,
1375+
enabled,
1376+
});
1377+
}
1378+
Ok(())
1379+
}
13101380
}
13111381
}
13121382

pallets/admin-utils/src/tests/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ pub(crate) fn run_to_block(n: u64) {
392392
while System::block_number() < n {
393393
SubtensorModule::on_finalize(System::block_number());
394394
System::on_finalize(System::block_number());
395+
System::reset_events();
395396
System::set_block_number(System::block_number() + 1);
396397
System::on_initialize(System::block_number());
397398
SubtensorModule::on_initialize(System::block_number());

pallets/admin-utils/src/tests/mod.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use pallet_subtensor::Event;
1111
use sp_consensus_grandpa::AuthorityId as GrandpaId;
1212
use sp_core::{ed25519, Pair, U256};
1313

14+
use crate::pallet::PrecompileEnable;
1415
use crate::Error;
1516
use mock::*;
1617

@@ -1365,3 +1366,74 @@ fn test_schedule_grandpa_change() {
13651366
assert_eq!(Grandpa::grandpa_authorities(), vec![(bob, 1)]);
13661367
});
13671368
}
1369+
1370+
#[test]
1371+
fn test_sudo_toggle_evm_precompile() {
1372+
new_test_ext().execute_with(|| {
1373+
let precompile_id = crate::PrecompileEnum::BalanceTransfer;
1374+
let initial_enabled = PrecompileEnable::<Test>::get(precompile_id);
1375+
assert!(initial_enabled); // Assuming the default is true
1376+
1377+
run_to_block(1);
1378+
1379+
assert_eq!(
1380+
AdminUtils::sudo_toggle_evm_precompile(
1381+
<<Test as Config>::RuntimeOrigin>::signed(U256::from(0)),
1382+
precompile_id,
1383+
false
1384+
),
1385+
Err(DispatchError::BadOrigin)
1386+
);
1387+
1388+
assert_ok!(AdminUtils::sudo_toggle_evm_precompile(
1389+
RuntimeOrigin::root(),
1390+
precompile_id,
1391+
false
1392+
));
1393+
1394+
assert_eq!(
1395+
System::events()
1396+
.iter()
1397+
.filter(|r| r.event
1398+
== RuntimeEvent::AdminUtils(crate::Event::PrecompileUpdated {
1399+
precompile_id,
1400+
enabled: false
1401+
}))
1402+
.count(),
1403+
1
1404+
);
1405+
1406+
let updated_enabled = PrecompileEnable::<Test>::get(precompile_id);
1407+
assert!(!updated_enabled);
1408+
1409+
run_to_block(2);
1410+
1411+
assert_ok!(AdminUtils::sudo_toggle_evm_precompile(
1412+
RuntimeOrigin::root(),
1413+
precompile_id,
1414+
false
1415+
));
1416+
1417+
// no event without status change
1418+
assert_eq!(
1419+
System::events()
1420+
.iter()
1421+
.filter(|r| r.event
1422+
== RuntimeEvent::AdminUtils(crate::Event::PrecompileUpdated {
1423+
precompile_id,
1424+
enabled: false
1425+
}))
1426+
.count(),
1427+
0
1428+
);
1429+
1430+
assert_ok!(AdminUtils::sudo_toggle_evm_precompile(
1431+
RuntimeOrigin::root(),
1432+
precompile_id,
1433+
true
1434+
));
1435+
1436+
let final_enabled = PrecompileEnable::<Test>::get(precompile_id);
1437+
assert!(final_enabled);
1438+
});
1439+
}

runtime/src/precompiles/mod.rs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use frame_support::dispatch::{GetDispatchInfo, Pays};
1717
use frame_system::RawOrigin;
1818
use sp_core::{hashing::keccak_256, H160};
1919
use sp_runtime::{traits::Dispatchable, AccountId32};
20+
21+
use pallet_admin_utils::{PrecompileEnable, PrecompileEnum};
2022
use sp_std::vec;
2123

2224
// Include custom precompiles
@@ -83,17 +85,59 @@ where
8385
// Non-Frontier specific nor Ethereum precompiles :
8486
a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)),
8587
a if a == hash(1025) => Some(ECRecoverPublicKey::execute(handle)),
88+
8689
a if a == hash(EDVERIFY_PRECOMPILE_INDEX) => Some(Ed25519Verify::execute(handle)),
8790
// Subtensor specific precompiles :
8891
a if a == hash(BALANCE_TRANSFER_INDEX) => {
89-
Some(BalanceTransferPrecompile::execute(handle))
92+
if PrecompileEnable::<Runtime>::get(PrecompileEnum::BalanceTransfer) {
93+
Some(BalanceTransferPrecompile::execute(handle))
94+
} else {
95+
Some(Err(PrecompileFailure::Error {
96+
exit_status: ExitError::Other(
97+
"Precompile Balance Transfer is disabled".into(),
98+
),
99+
}))
100+
}
101+
}
102+
a if a == hash(STAKING_PRECOMPILE_INDEX) => {
103+
if PrecompileEnable::<Runtime>::get(PrecompileEnum::Staking) {
104+
Some(StakingPrecompile::execute(handle))
105+
} else {
106+
Some(Err(PrecompileFailure::Error {
107+
exit_status: ExitError::Other(
108+
"Precompile Balance Transfer is disabled".into(),
109+
),
110+
}))
111+
}
112+
}
113+
114+
a if a == hash(SUBNET_PRECOMPILE_INDEX) => {
115+
if PrecompileEnable::<Runtime>::get(PrecompileEnum::Subnet) {
116+
Some(SubnetPrecompile::execute(handle))
117+
} else {
118+
Some(Err(PrecompileFailure::Error {
119+
exit_status: ExitError::Other("Precompile Subnet is disabled".into()),
120+
}))
121+
}
90122
}
91-
a if a == hash(STAKING_PRECOMPILE_INDEX) => Some(StakingPrecompile::execute(handle)),
92-
a if a == hash(SUBNET_PRECOMPILE_INDEX) => Some(SubnetPrecompile::execute(handle)),
93123
a if a == hash(METAGRAPH_PRECOMPILE_INDEX) => {
94-
Some(MetagraphPrecompile::execute(handle))
124+
if PrecompileEnable::<Runtime>::get(PrecompileEnum::Metagraph) {
125+
Some(MetagraphPrecompile::execute(handle))
126+
} else {
127+
Some(Err(PrecompileFailure::Error {
128+
exit_status: ExitError::Other("Precompile Metagrah is disabled".into()),
129+
}))
130+
}
131+
}
132+
a if a == hash(NEURON_PRECOMPILE_INDEX) => {
133+
if PrecompileEnable::<Runtime>::get(PrecompileEnum::Neuron) {
134+
Some(NeuronPrecompile::execute(handle))
135+
} else {
136+
Some(Err(PrecompileFailure::Error {
137+
exit_status: ExitError::Other("Precompile Neuron is disabled".into()),
138+
}))
139+
}
95140
}
96-
a if a == hash(NEURON_PRECOMPILE_INDEX) => Some(NeuronPrecompile::execute(handle)),
97141

98142
_ => None,
99143
}

0 commit comments

Comments
 (0)