-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
Problem
The staking precompile defines SYSTEM_ADDRESS = Address::ZERO, which creates a security risk because the zero address is commonly used as a default/null value elsewhere in Ethereum.
Location
crates/execution/src/precompiles/staking.rs:22-24
Code Analysis
/// System address allowed to call slash function.
///
/// In production, this should be the consensus layer's system account.
pub const SYSTEM_ADDRESS: Address = Address::ZERO;This is used in the slash() function:
fn slash(&self, data: &[u8], gas_limit: u64, caller: Address) -> PrecompileResult {
// ...
// Only callable by system
if caller != SYSTEM_ADDRESS {
return Err(PrecompileError::Fatal(
"Unauthorized: system-only function".to_string(),
));
}
// ... performs slash
}Security Concern
Address::ZERO (0x0000...0000) is problematic because:
- Common default value: Many Ethereum libraries and contracts use Address::ZERO as a sentinel/null value
- Accidental matches: A bug elsewhere in the code that leaves an address uninitialized could accidentally match the system address
- Transfer destination: The zero address is often used as a burn address
- CREATE operation: Contract creation transactions have
to: Address::ZERO, though this doesn't affect precompile calls directly
Production Risk
The comment itself acknowledges this is temporary:
/// In production, this should be the consensus layer's system account.
If deployed as-is, anyone who can make a call with caller=Address::ZERO could slash validators.
Suggested Fix
Use a dedicated system address derived deterministically:
/// System address for privileged operations.
/// Derived as keccak256("CipherBFT.SystemAddress")[12..32]
pub const SYSTEM_ADDRESS: Address = address!("1111111111111111111111111111111111111111");
// Or use a canonical Ethereum system address pattern
// pub const SYSTEM_ADDRESS: Address = address!("fffffffffffffffffffffffffffffffffffffffe");Alternative: Make it configurable at genesis:
pub struct StakingPrecompile {
state: Arc<RwLock<StakingState>>,
system_address: Address, // Configurable
}
impl StakingPrecompile {
pub fn new(system_address: Address) -> Self {
Self {
state: Arc::new(RwLock::new(StakingState::default())),
system_address,
}
}
}Severity
High - Security vulnerability that could allow unauthorized slashing if any code path creates calls with uninitialized/zero addresses.