Coinflip

Published by Mario Oettler on

Dieser Exploit funktioniert nicht auf der virtuellen Blockchain, die von Remix bereitgestellt wird. Nutzen Sie daher das Sepolia Testnetzwerk. Melden Sie sich dazu in MetaMask an und stellen Sie in Remix die Environment auf “Injected Provider (MetaMask)”.

Gegeben ist folgender Contract:

pragma solidity ^0.8.21;
contract CoinFlip {
  uint256 public consecutiveWins;
  uint256 lastHash;
  uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968; // Factor ist so gewählt, dass in der Berechnung in Zeile 23 entweder 0 oder 1 rauskommt.
 
  uint256 public blockValue;
  bool public myGuess;
  bool public side;
  constructor() {
    consecutiveWins = 0;
  }
 
  function flip(bool _guess) public returns (bool win){
    blockValue = uint256(blockhash(block.number-1));
    myGuess = _guess;
    
    if (lastHash == blockValue) {
      revert("Gleiche Bloecke");
    }
 
    lastHash = blockValue;
    uint256 coinFlip = blockValue / FACTOR;
    side = coinFlip == 1 ? true : false;
 
    if (side == _guess) {
      consecutiveWins++;
      //return true;
    } else {
      consecutiveWins = 0;
      //return false;
    }
  }
}

Versuchen Sie, zehn Mal hintereinander die richtige Seite der Münze zu werfen. (consecutiveWins = 10);

Erklärung Coinflip-Contract:

1. Schutz vor mehreren TX in einem Block

if (lastHash == blockValue) {
    revert();
}
 
lastHash = blockValue;

Wenn mehr als 1 TX im Block ist, die flip() auruft, wird nur die erste TX genommen.

2. Münzwurf

uint256 coinFlip = blockValue / FACTOR;

FACTOR = 2^255 Bit lang. Damit hängt das Ergebnis der Division nur von dem 1. (ganz linken Bit von blockValue ab. Ist dieses 1, ist coinFlip = 1, ist dieses 0, ist coinFlip = 0.)

3. Conditional Operator

bool side = coinFlip == 1 ? true : false;

Wenn coinFlip == 1, dann wird side = true, ansonsten wird side = false.

4. Länge der Glückssträhne

uint256 public consecutiveWins;
 
if (side == _guess) {
   consecutiveWins++;
   return true;
} else {
   consecutiveWins = 0;
   return false;
}

consecutiveWins ist eine öffentliche Variable.

Wenn side = _guess, wird die Zahl der zusammenhängenden richtigen Angaben (consecutiveWins) um 1 erhöht.

Wenn side != _guess, wird die Zahl der zusammenhängenden richtigen Angaben (consecutiveWins) = 0 gesetzt.

Lösung

Categories: