Centralization Risks
Detects excessive owner privileges, single points of failure, and centralization patterns that enable rug pulls or administrative abuse.
Centralization Risks
Overview
Remediation Guide: How to Fix Centralization Risks
The centralization detector identifies contracts where a single address (owner, admin, or governance) has disproportionate control over critical operations. This includes the ability to pause/unpause, change fees to 100%, drain funds, modify access control, or upgrade the implementation without timelocks or multisig requirements.
Why This Is an Issue
Centralization is consistently ranked in the OWASP Smart Contract Top 10 (2025, position #5). A compromised or malicious owner key can:
- Drain all user funds via privileged transfer functions
- Freeze all operations indefinitely via pause without timelock
- Set fees to 100%, redirecting all revenue
- Upgrade to a malicious implementation via unprotected proxy upgrade
The Multichain exploit ($126M, 2023) resulted from a single compromised key. Numerous rug pulls exploit onlyOwner functions that can arbitrarily mint tokens, change swap parameters, or directly transfer user deposits.
How to Resolve
// Before: Single owner can drain funds instantly
function emergencyWithdraw(address token) external onlyOwner {
IERC20(token).transfer(owner, IERC20(token).balanceOf(address(this)));
}
// After: Timelock + multisig + limited scope
function emergencyWithdraw(address token) external onlyRole(EMERGENCY_ROLE) {
require(block.timestamp >= emergencyRequestTimestamp + TIMELOCK_DELAY, "Timelock");
require(emergencyApprovals >= REQUIRED_APPROVALS, "Insufficient approvals");
IERC20(token).transfer(emergencyRecipient, IERC20(token).balanceOf(address(this)));
emit EmergencyWithdrawal(token, msg.sender);
}
Examples
Vulnerable Code
contract CentralizedToken {
address public owner;
function mint(address to, uint256 amount) external {
require(msg.sender == owner); // Single key controls supply
_mint(to, amount);
}
function setFee(uint256 fee) external {
require(msg.sender == owner);
transferFee = fee; // Can set to 100%, stealing all transfers
}
function pause() external {
require(msg.sender == owner);
paused = true; // No timelock, no unpause guarantee
}
}
Fixed Code
contract DecentralizedToken is AccessControl {
uint256 constant MAX_FEE = 500; // 5% cap
uint256 constant TIMELOCK = 48 hours;
function setFee(uint256 fee) external onlyRole(GOVERNANCE_ROLE) {
require(fee <= MAX_FEE, "Fee exceeds cap");
require(block.timestamp >= feeChangeRequest + TIMELOCK, "Timelock");
transferFee = fee;
emit FeeUpdated(fee);
}
function pause() external onlyRole(GUARDIAN_ROLE) {
paused = true;
pauseExpiry = block.timestamp + 72 hours; // Auto-unpause after 72h
emit Paused(msg.sender, pauseExpiry);
}
}
Sample Sigvex Output
{
"detector_id": "centralization",
"severity": "high",
"confidence": 0.85,
"description": "Owner address can call mint() to create unlimited tokens without timelock, multisig, or supply cap. Single key compromise enables infinite token minting.",
"location": { "function": "mint(address,uint256)", "offset": 64 }
}
Detection Methodology
- Privilege enumeration: Identifies all functions gated by owner/admin checks (comparison against storage slot 0 or Ownable pattern).
- Impact assessment: Classifies privileged operations by risk: fund movement (critical), parameter changes (high), view functions (low).
- Mitigation detection: Checks for timelocks, multisig patterns, parameter caps, and role separation.
- Scoring: Higher severity when multiple high-impact operations are controlled by a single address without mitigations.
Limitations
- Cannot distinguish between a single EOA owner and a multisig contract at the same address — both appear as a single
require(msg.sender == X)check. - Off-chain governance (e.g., Gnosis Safe with multi-party signing) is invisible at the bytecode level.
- Timelocks implemented in a separate contract via cross-contract calls may not be detected.
Related Detectors
- Access Control — missing or improper access controls
- Governance Attacks — governance manipulation
- Unprotected Ether Withdrawal — ether withdrawal without access control