Skip to content

Instantly share code, notes, and snippets.

@grantjoy
Last active July 19, 2023 21:13
Show Gist options
  • Save grantjoy/0d0d5255625b37eaee35a0c7c36a5258 to your computer and use it in GitHub Desktop.
Save grantjoy/0d0d5255625b37eaee35a0c7c36a5258 to your computer and use it in GitHub Desktop.
Coin Flip Contract
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;
contract CoinFlip {
enum CoinSide {HEADS, TAILS, UNKNOWN}
CoinSide public winSide = CoinSide.UNKNOWN;
struct Bet {
uint256 amount;
address payable bettor;
}
mapping(CoinSide => Bet) public bets;
mapping(CoinSide => uint256) public wins;
uint256 private constant BET_AMOUNT = 0.01 ether;
uint256 private constant SIDES = 2;
event BetPlaced(CoinSide winSide, address winAddress);
event WinSideDeclared(CoinSide winSide, address winAddress, address loseAddress);
function bet(CoinSide side) external payable {
require(msg.value == BET_AMOUNT, "Bet amount must be 0.01 Ether");
require(bets[side].amount == 0, "A bet for this side has already been placed");
bets[side] = Bet(msg.value, payable(msg.sender));
emit BetPlaced(side, msg.sender);
if (bets[CoinSide.HEADS].amount == BET_AMOUNT && bets[CoinSide.TAILS].amount == BET_AMOUNT) {
flip();
}
}
function flip() internal {
require(bets[CoinSide.HEADS].amount == BET_AMOUNT, "Heads bet not set");
require(bets[CoinSide.TAILS].amount == BET_AMOUNT, "Tails bet required");
require(address(this).balance >= BET_AMOUNT * SIDES, "Insufficient contract balance");
winSide = getWinSide();
CoinSide loseSide = (winSide == CoinSide.HEADS ? CoinSide.TAILS : CoinSide.HEADS);
address loseAddress = bets[loseSide].bettor;
address payable winAddress = bets[winSide].bettor;
wins[winSide]++;
winAddress.transfer(BET_AMOUNT * SIDES);
emit WinSideDeclared(winSide, winAddress, loseAddress);
reset();
}
function getWinSide() internal view returns (CoinSide) {
uint256 random = uint256(keccak256(abi.encodePacked(block.timestamp)));
return CoinSide(random % SIDES);
}
function reset() internal {
delete bets[CoinSide.HEADS];
delete bets[CoinSide.TAILS];
winSide = CoinSide.UNKNOWN;
}
function getBet(CoinSide side) public view returns (uint256, address) {
return (bets[side].amount, bets[side].bettor);
}
function getWins(CoinSide side) public view returns (uint256) {
return wins[side];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment