Skip to content
Back to skills

2603 Weak Sources Randomness 34b619d7

ASecurity

- Contract generates "random" values using on-chain data: `block.timestamp`, `blockhash`, `block.difficulty` / `block.prevrandao`, `block.number`, or combinations thereof - The random value determines outcomes with economic value (lotteries, games, minting, distributions)

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
blockchain

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2603-weak-sources-randomness_34b619d7 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2603 Weak Sources Randomness 34b619d7?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2603 Weak Sources Randomness 34b619d7
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2603-weak-sources-randomness-34b619d7/badge)](https://www.skillsdirectory.com/skills/tools-only-2603-weak-sources-randomness-34b619d7)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Weak Sources of Randomness from Chain Attributes

## Preconditions
- Contract generates "random" values using on-chain data: `block.timestamp`, `blockhash`, `block.difficulty` / `block.prevrandao`, `block.number`, or combinations thereof
- The random value determines outcomes with economic value (lotteries, games, minting, distributions)

## Vulnerable Pattern
```solidity
function drawLottery() external {
    // All inputs are deterministic and publicly visible
    // Another contract can compute the same value in the same tx
    uint256 random = uint256(keccak256(abi.encodePacked(
        block.timestamp,
        block.prevrandao,
        msg.sender
    ))) % 100;

    if (random < 5) {
        _payWinner(msg.sender);
    }
}

// Attacker contract
contract Exploit {
    function attack(Lottery target) external {
        // Compute the same "random" value before calling
        uint256 random = uint256(keccak256(abi.encodePacked(
            block.timestamp,
            block.prevrandao,
            address(this)
        ))) % 100;

        // Only call if we'll win
        if (random < 5) {
            target.drawLottery();
        }
    }
}
```

## Detection Heuristics
1. Search for `block.timestamp`, `block.prevrandao`, `block.difficulty`, `blockhash`, `block.number` used as inputs to `keccak256` or arithmetic operations producing a "random" value
2. Check if the resulting value determines an outcome with economic impact (winner selection, token distribution, NFT rarity, game outcome)
3. If randomness is derived exclusively from on-chain data, flag it — a contract in the same transaction can compute the identical value
4. Check if `blockhash` is used for a future block (returns 0 for blocks not yet mined) or a block older than 256 blocks (also returns 0)
5. Check if validators/miners can influence the inputs to bias the outcome

## False Positives
- Chainlink VRF or another verifiable randomness oracle is used
- On-chain data is combined with an off-chain commit-reveal scheme (the on-chain part alone doesn't determine the outcome)
- The randomness doesn't determine anything with economic value
- `block.prevrandao` on PoS Ethereum provides sufficient entropy for the specific use case (not for high-value outcomes)

## Remediation
- Use Chainlink VRF (Verifiable Random Function) for provably fair randomness
- Implement a commit-reveal scheme: users commit hashed choices, reveal in a later block
- Never use `block.timestamp`, `blockhash`, or `block.prevrandao` alone for randomness in high-value contexts
```solidity
import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";

contract FairLottery is VRFConsumerBaseV2 {
    function requestRandom() external {
        requestRandomWords(keyHash, subId, confirmations, gasLimit, 1);
    }

    function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override {
        uint256 winner = randomWords[0] % participants.length;
        _payWinner(participants[winner]);
    }
}
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…