Insecure Randomness
id: LS03H
title: Insecure Randomness
baseSeverity: H
category: randomness
language: solidity
blockchain: [ethereum]
impact: Predictable outcomes in games, lotteries, or rewards
status: draft
complexity: medium
attack_vector: external
mitigation_difficulty: medium
versions: [">=0.4.0", "<0.8.21"]
cwe: CWE-330
swc: SWC-120
๐ Description
- Insecure randomness occurs when a contract attempts to generate "random" values using predictable on-chain inputs like
block.timestamp,blockhash,msg.sender, orblock.number. - Since miners or attackers can influence or observe these values, the resulting "randomness" can be predicted or manipulatedโleading to unfair outcomes in lotteries, games, reward distributions, and token mints.
๐จ Vulnerable Code
contract Lottery {
address[] public players;
function enter() external payable {
players.push(msg.sender);
}
function pickWinner() external {
uint256 index = uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender))) % players.length;
payable(players[index]).transfer(address(this).balance);
}
}
๐งช Exploit Scenario
Step-by-step exploit process:
- Attacker observes that pickWinner() uses block.timestamp and msg.sender.
- They can precompute the winner by simulating the hash locally.
- If not the winner, they donโt call the function. If yes, they call it and win.
- In low-activity contracts, attacker may even influence the timestamp (if they're the miner or use front-running).
Assumptions:
- No external source of entropy.
- All randomness derived from on-chain, attacker-readable inputs.
โ Fixed Code
// Uses Chainlink VRF (Verifiable Random Function)
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract SecureLottery is VRFConsumerBase {
bytes32 internal keyHash;
uint256 internal fee;
uint256 public randomResult;
constructor()
VRFConsumerBase(<vrfCoordinator>, <linkToken>)
{
keyHash = <your_key_hash>;
fee = <your_fee>;
}
function getRandomNumber() public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK");
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
}
}
๐งญ Contextual Severity
- context: "Randomness used for reward distribution, winner selection, or access control"
severity: H
reasoning: "Allows attacker to manipulate economic outcomes"
- context: "Used only for cosmetic effects (e.g., UI colors)
severity: L
reasoning: "Low or no economic risk"
- context: "Verifiable randomness or commit-reveal used"
severity: I
reasoning: "No vulnerability present"
๐ก๏ธ Prevention
Primary Defenses
- Use Chainlink VRF, Redstone, Witnet, or other verifiable randomness protocols.
- If off-chain randomness is not an option, use commit-reveal schemes with multiple parties.
Additional Safeguards
- Use delay or block-lag logic to reduce miner predictability.
- Combine multiple entropy sources including signed off-chain data.
Detection Methods
- Slither: weak-prng, block-dependent detectors.
- Manual inspection of hash-based randomness using public inputs.
- Static rule engines for entropy misuse.
๐ฐ๏ธ Historical Exploits
- Name: Roast Football Protocol Exploit
- Date: 2022-12-05
- Loss: Undisclosed
- Post-mortem: Link to post-mortem
๐ Further Reading
- SC09: Insecure Randomness โ OWASP Smart Contract Security
- Smart Contracts Vulnerability Explained: Insecure Randomness
- Insecure Randomness in Smart Contracts โ Metana
โ Vulnerability Report
id: LS03H
title: Insecure Randomness
severity: H
score:
impact: 5
exploitability: 4
reachability: 4
complexity: 3
detectability: 3
finalScore: 4.25
๐ Justifications & Analysis
- Impact: Affected contracts lose trust; attackers can rig games, NFTs, and rewards.
- Exploitability: Simple to simulate locally or time with flashbots if predictable.
- Reachability: Often exposed through open draw() or pickWinner() logic.
- Complexity: Requires understanding of entropy flow, but no special infra.
- Detectability: Static analyzers like Slither flag this reliably, but not all hash patterns are caught.