Skip to content

Instantly share code, notes, and snippets.

@edwinosky
Created August 26, 2024 03:44
Show Gist options
  • Save edwinosky/a3cc9793dbd454c2ca64a78f4ad93433 to your computer and use it in GitHub Desktop.
Save edwinosky/a3cc9793dbd454c2ca64a78f4ad93433 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.26+commit.8a97fa7a.js&optimize=false&runs=200&gist=
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract BettingContract is Ownable, ReentrancyGuard {
AggregatorV3Interface internal priceFeed;
struct Bet {
address user;
uint256 amount;
bool isUp;
uint256 timestamp;
bool claimed;
}
mapping(address => Bet[]) public userBets;
mapping(address => uint256) public userBalances;
uint256 public minimumBet = 0.0001 ether;
uint256 public roundDuration = 5 minutes;
uint256 public currentRoundEnd;
uint256 public roundNumber;
event BetPlaced(address indexed user, uint256 amount, bool isUp, uint256 timestamp);
event BetResolved(address indexed user, uint256 amountWon, bool isWinner, uint256 timestamp);
event Claimed(address indexed user, uint256 amount);
event RoundClosed(uint256 roundNumber, uint256 timestamp);
constructor(address _priceFeed) Ownable(msg.sender) {
priceFeed = AggregatorV3Interface(_priceFeed);
currentRoundEnd = block.timestamp + roundDuration;
roundNumber = 1;
}
function placeBet(bool _isUp) external payable {
require(block.timestamp < currentRoundEnd, "Betting is closed for this round");
require(msg.value >= minimumBet, "Bet amount too low");
Bet memory newBet = Bet({
user: msg.sender,
amount: msg.value,
isUp: _isUp,
timestamp: block.timestamp,
claimed: false
});
userBets[msg.sender].push(newBet);
emit BetPlaced(msg.sender, msg.value, _isUp, block.timestamp);
}
function resolveBet(address _user, bool _isWinner) external onlyOwner nonReentrant {
Bet[] storage bets = userBets[_user];
require(bets.length > 0, "No bets found");
uint256 totalWon = 0;
for (uint256 i = 0; i < bets.length; i++) {
if (!bets[i].claimed && bets[i].isUp == _isWinner) {
uint256 amountWon = bets[i].amount * 2;
totalWon += amountWon;
bets[i].claimed = true;
emit BetResolved(_user, amountWon, true, block.timestamp);
} else if (!bets[i].claimed) {
bets[i].claimed = true;
emit BetResolved(_user, 0, false, block.timestamp);
}
}
if (totalWon > 0) {
userBalances[_user] += totalWon;
}
}
function claim() external nonReentrant {
uint256 balance = userBalances[msg.sender];
require(balance > 0, "No balance to claim");
userBalances[msg.sender] = 0;
payable(msg.sender).transfer(balance);
emit Claimed(msg.sender, balance);
}
function getUserBets(address _user) external view returns (Bet[] memory) {
return userBets[_user];
}
function getLatestPrice() public view returns (int256) {
(
,
int256 price,
,
,
) = priceFeed.latestRoundData();
return price;
}
function startNewRound() external onlyOwner {
require(block.timestamp >= currentRoundEnd, "Current round is not yet over");
currentRoundEnd = block.timestamp + roundDuration;
roundNumber++;
emit RoundClosed(roundNumber, block.timestamp);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment