10 Faces of Blockchain Security (Part 3)
Consensus-Level Attacks & Access Control Failures
So far we’ve covered the contract layer (Part 1) and the economic layer (Part 2). Part 3 splits in two directions. One targets the blockchain’s foundation — the consensus algorithm itself (the 51% attack). The other is an access control failure, where a contract fails to properly decide “who is allowed to call this function.” Different layers, but they share one thing: a boundary of authority collapses.
7. The 51% Attack (Majority Hashpower/Stake Attack)
The vulnerability
The security of a Proof-of-Work blockchain rests on the assumption that “honest participants hold the majority of hashpower.” If a single actor acquires a majority of the hashpower, they can produce blocks faster than anyone else and build their own longer chain. Because of the longest-chain rule — the longest chain is accepted as valid — this attacker can replace (reorg) the existing chain with theirs.
Exploit flow — double spend
- The attacker sends coins to an exchange on the honest chain (transaction A).
- Simultaneously, they privately mine a separate chain in which transaction A does not exist.
- The exchange confirms transaction A and gives the attacker goods / another coin.
- The attacker publishes their privately-mined, now-longer chain. The network adopts the longer chain as canonical.
- Since the chain without transaction A is now canonical, the attacker gets their coins back and keeps the goods — spending the same coins twice.
The crucial point: there is no contract bug at all. The protocol worked exactly by its rules; only the safety assumption behind those rules (honest majority) was broken.
Real cases
- Ethereum Classic (ETC): hit by 51% attacks several times in 2019–2020, resulting in double spends and chain reorgs in the hundreds of thousands to over a million dollars.
- Bitcoin Gold: suffered roughly $18M in double-spend losses from a 51% attack in 2018.
The common thread: small-hashpower chains. The lower the total hashrate, the cheaper it is to rent or acquire a majority, making the attack economically viable. Large chains like Bitcoin and Ethereum are effectively protected because acquiring a majority would cost astronomically.
Defense patterns
- More confirmations: for larger transactions, wait for more block confirmations. Overturning them via reorg requires digging that much deeper, sharply raising attack cost.
- Switch to PoS: under Proof-of-Stake, an attack gets the staked funds slashed — the attack literally destroys the attacker’s own assets. This was a core motivation behind Ethereum’s Merge.
- Checkpointing: periodically fix trusted checkpoints, blocking any reorg past that point.
- Hashrate distribution monitoring: raise an early warning when any single pool’s share approaches a dangerous level.
8. Access Control Failures (Parity Multisig, 2017)
The vulnerability
A contract’s sensitive functions — withdrawing funds, changing ownership, self-destructing — must restrict “who can call them.” If a modifier like onlyOwner or an initialization guard is missing, anyone can call that function.
Exploit flow
// Vulnerable: no guard on the init function, so anyone can re-initialize
contract Wallet {
address public owner;
// no initializer guard!
function initWallet(address _owner) public {
owner = _owner; // an attacker can set themselves as owner
}
function withdraw(uint amount) public {
require(msg.sender == owner);
payable(msg.sender).transfer(amount);
}
}
For an already-initialized wallet, the attacker simply calls initWallet(attacker) again, and ownership transfers to them. Then they drain the funds via withdraw.
Real case — Parity’s two incidents
First (July 2017): the Parity multisig wallet’s init function was unprotected in a manner similar to the above. An attacker reset ownership of the wallets and stole roughly $30M.
Second (November 2017): this one is more striking. Parity wallets delegated their logic (via delegatecall) to a single shared library contract. That library was itself uninitialized, and its kill() (self-destruct) function was unprotected. A user named devops199 accidentally initialized the library as their own, then called self-destruct. Instantly, every multisig wallet depending on that library was bricked, permanently freezing over $500M. What made it especially painful: this wasn’t theft but permanent loss of access.
The second incident is actually a combination of the delegatecall/storage vulnerability from Part 1 and an access control failure. Uninitialized library + unprotected destructor = catastrophe.
Defense patterns
- Explicit access modifiers: apply
onlyOwneror role-based access (OpenZeppelinAccessControl) to every sensitive function. - Initialization guards: use the
initializermodifier to enforce that the init function runs exactly once. - Initialize on deploy: initialize implementation/library contracts immediately after deployment, leaving no “ownerless” state.
- Use self-destruct cautiously: minimize destructor functions, and if you keep them, guard them strictly. (Solidity itself is moving to discourage
selfdestruct.)
// Safe: init runs once, destructor is owner-only
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract Wallet is Initializable {
address public owner;
function initialize(address _owner) public initializer { // runs once only
owner = _owner;
}
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
}
Part 3 Summary
| # | Problem | Boundary that collapsed | Notable case | Core defense |
|---|---|---|---|---|
| 7 | 51% attack | Consensus honest-majority assumption | ETC, Bitcoin Gold | More confirmations · PoS |
| 8 | Access control failure | Function call authority | Parity (two cases) | initializer · onlyOwner |
The 51% attack is a collapse of the protocol’s safety assumption; the access control failure is a collapse of the contract’s authority boundary. Both arise when the answer to “who is allowed to do what” comes undone.
In the final Part 4, we leave on-chain code entirely. We cover replay attacks, where a signature is reused out of context, and the off-chain key theft behind the largest hack in history — the Ronin bridge.
This article is part of the ChainLab technical series.
Tags: BlockchainSecurity, 51PercentAttack, DoubleSpend, AccessControl, Parity