├── .prettierrc ├── .solhintignore ├── .npmignore ├── .eslintignore ├── frontend ├── src │ ├── react-app-env.d.ts │ ├── components │ │ ├── ui │ │ │ └── Brand.tsx │ │ ├── casinoGames │ │ │ └── Blackjack │ │ │ │ ├── Blackjack.css │ │ │ │ └── Blackjack.tsx │ │ ├── ClaimChips.tsx │ │ └── WalletConnector.tsx │ ├── utils │ │ ├── types.ts │ │ ├── environment.ts │ │ ├── connectors.ts │ │ ├── provider.ts │ │ └── hooks.ts │ ├── setupTests.ts │ ├── App.test.tsx │ ├── index.css │ ├── index.tsx │ ├── reportWebVitals.ts │ ├── pages │ │ ├── CasinoGame.tsx │ │ ├── LandingPage.tsx │ │ └── RoulettePage.tsx │ ├── App.tsx │ ├── BlackJack │ │ ├── style.css │ │ ├── index.html │ │ └── blackjack.js │ ├── App.css │ ├── hooks │ │ └── useRoulette.ts │ └── logo.svg ├── types │ └── react-free-playing-cards │ │ └── index.d.ts ├── public │ ├── logo.png │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── .env.example ├── .gitignore ├── tsconfig.json ├── package.json └── README.md ├── .prettierignore ├── .gitignore ├── .solhint.json ├── tsconfig.json ├── .env.example ├── .github └── workflows │ └── hardhat.yml ├── .eslintrc.js ├── hardhat.config.ts ├── package.json ├── test └── index.ts ├── contracts ├── Chip.sol ├── Casino.sol ├── CasinoGame.sol ├── Roulette.sol └── Blackjack.sol ├── scripts └── deploy.ts ├── CODE_OF_CONDUCT.md ├── PROPOSAL.md ├── README.md └── LICENSE /.prettierrc: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.solhintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | hardhat.config.ts 2 | scripts 3 | test 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage 5 | -------------------------------------------------------------------------------- /frontend/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage* 5 | gasReporterOutput.json 6 | -------------------------------------------------------------------------------- /frontend/types/react-free-playing-cards/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-free-playing-cards/lib/TcN'; -------------------------------------------------------------------------------- /frontend/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jweiss0/OSS-CryptoCasino/HEAD/frontend/public/logo.png -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jweiss0/OSS-CryptoCasino/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jweiss0/OSS-CryptoCasino/HEAD/frontend/public/logo192.png -------------------------------------------------------------------------------- /frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jweiss0/OSS-CryptoCasino/HEAD/frontend/public/logo512.png -------------------------------------------------------------------------------- /frontend/src/components/ui/Brand.tsx: -------------------------------------------------------------------------------- 1 | export const Brand = () => { 2 | return cryptocasino; 3 | }; 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | 7 | #Hardhat files 8 | cache 9 | artifacts 10 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": ["error", "^0.8.0"], 5 | "func-visibility": ["warn", { "ignoreConstructors": true }] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/utils/types.ts: -------------------------------------------------------------------------------- 1 | export interface BlackjackHand { 2 | isBust: boolean; 3 | isBlackjack: boolean; 4 | isDoubledDown: boolean; 5 | fromSplit: boolean; 6 | bet: string; 7 | cVals: string[]; 8 | cSuits: string[]; 9 | } -------------------------------------------------------------------------------- /frontend/src/utils/environment.ts: -------------------------------------------------------------------------------- 1 | export const CasinoContractAddr = process.env.REACT_APP_CASINO_CONTRACT_ADDR; 2 | export const BlackjackContractAddr = process.env.REACT_APP_BLACKJACK_CONTRACT_ADDR; 3 | export const ChipContractAddr = process.env.REACT_APP_CHIP_CONTRACT_ADDR; -------------------------------------------------------------------------------- /frontend/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /frontend/.env.example: -------------------------------------------------------------------------------- 1 | REACT_APP_CASINO_CONTRACT_ADDR=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 2 | REACT_APP_BLACKJACK_CONTRACT_ADDR=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 3 | REACT_APP_CHIP_CONTRACT_ADDR=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "declaration": true 9 | }, 10 | "include": ["./scripts", "./test", "./typechain"], 11 | "files": ["./hardhat.config.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1 2 | MUMBAI_URL=https://polygon-mumbai.g.alchemy.com/v2/ 3 | MUMBAI_PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 4 | CASINO_CONTRACT_ADDR=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 5 | BLACKJACK_CONTRACT_ADDR=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import { Web3ReactProvider } from '@web3-react/core'; 6 | import { getProvider } from './utils/provider'; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | 12 | 13 | , 14 | document.getElementById('root') 15 | ); -------------------------------------------------------------------------------- /frontend/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /frontend/src/components/casinoGames/Blackjack/Blackjack.css: -------------------------------------------------------------------------------- 1 | .blackjack-page { 2 | padding-top: 100px; 3 | padding-bottom: 100px; 4 | } 5 | 6 | .game-btn { 7 | color: white; 8 | font-family: "Righteous", cursive; 9 | } 10 | 11 | .btn-dec { 12 | background-color: #D3455B; 13 | } 14 | 15 | .btn-inc { 16 | background-color: #207868; 17 | } 18 | 19 | .card-list { 20 | position: relative; 21 | display: flex; 22 | } 23 | 24 | .card { 25 | display: inline-block; 26 | height: 200px; 27 | } -------------------------------------------------------------------------------- /.github/workflows/hardhat.yml: -------------------------------------------------------------------------------- 1 | name: Hardhat Compile & Tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | 11 | - name: Use Node.js 16.x 12 | uses: actions/setup-node@v3 13 | with: 14 | node-version: 16.x 15 | 16 | - name: Upgrade NPM 17 | run: npm install -g npm 18 | 19 | - name: Install Dependencies 20 | run: npm ci 21 | 22 | - name: Compile Contracts 23 | run: npx hardhat compile 24 | 25 | - name: Run Tests 26 | run: npx hardhat test 27 | -------------------------------------------------------------------------------- /frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: false, 4 | es2021: true, 5 | mocha: true, 6 | node: true, 7 | }, 8 | plugins: ["@typescript-eslint"], 9 | extends: [ 10 | "standard", 11 | "plugin:prettier/recommended", 12 | "plugin:node/recommended", 13 | ], 14 | parser: "@typescript-eslint/parser", 15 | parserOptions: { 16 | ecmaVersion: 12, 17 | }, 18 | rules: { 19 | "node/no-unsupported-features/es-syntax": [ 20 | "error", 21 | { ignores: ["modules"] }, 22 | ], 23 | "prettier/prettier": [ 24 | "error", 25 | { endOfLine: ["auto"]} 26 | ] 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /frontend/src/pages/CasinoGame.tsx: -------------------------------------------------------------------------------- 1 | import { Blackjack } from '../components/casinoGames/Blackjack/Blackjack'; 2 | 3 | export interface IParams { 4 | mode: string; // game mode (blackjack, roulette, slots) 5 | } 6 | 7 | export const CasinoGame = (params: IParams) => { 8 | return ( 9 |
10 |
11 | {params.mode === "blackjack" ? : <>} 12 | {/* {params.mode === "Roulette" ? : <>} */} 13 | {/* {params.mode === "Slots" ? : <>} */} 14 |
15 |
16 | ); 17 | }; 18 | 19 | export default CasinoGame; 20 | -------------------------------------------------------------------------------- /frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; 2 | import LandingPage from "./pages/LandingPage"; 3 | import RoulettePage from "./pages/RoulettePage"; 4 | import CasinoGame from "./pages/CasinoGame"; 5 | import "bootstrap/dist/css/bootstrap.css"; 6 | import "./App.css"; 7 | 8 | const App = () => { 9 | return ( 10 | 11 | 12 | } /> 13 | } /> 14 | } /> 15 | {/* } /> */} 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx", 22 | "typeRoots": [ "./types", "./node_modules/@types"] 23 | }, 24 | "include": [ 25 | "src", "./types" 26 | ], 27 | "exclude": ["node_modules", "typings"] 28 | } 29 | -------------------------------------------------------------------------------- /frontend/src/BlackJack/style.css: -------------------------------------------------------------------------------- 1 | 2 | :root { 3 | background-color:rgb(203, 242, 255); 4 | font-size: 62.5%; 5 | } 6 | 7 | h1 { 8 | color: rgb(4, 30, 73); 9 | margin: auto; 10 | } 11 | 12 | .container { 13 | background-color: rgb(126, 255, 244); 14 | color: black; 15 | width: 90%; 16 | margin: auto; 17 | padding: 30px 0; 18 | border: 4px solid rgb(78, 175, 78); 19 | } 20 | 21 | .btn { 22 | display: inline-block; 23 | border: 1px solid #FFA800; 24 | height: 50px; 25 | width: 75px; 26 | margin:0 auto; 27 | background-color: white; 28 | } 29 | 30 | .hand { 31 | background-color: rgb(254, 255, 191); 32 | color: black; 33 | width: 60%; 34 | margin: auto; 35 | padding: auto; 36 | border: 2px white; 37 | } 38 | 39 | .card { 40 | background-color: white; 41 | display: inline-block; 42 | border: 3px solid black; 43 | margin: 7px; 44 | padding: 30px; 45 | height: 45px; 46 | width: 30px; 47 | text-align: center; 48 | } 49 | 50 | .center { 51 | text-align: center; 52 | } 53 | -------------------------------------------------------------------------------- /frontend/src/pages/LandingPage.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { WalletConnector } from "../components/WalletConnector"; 3 | import { ClaimChips } from "../components/ClaimChips"; 4 | 5 | export const LandingPage = () => { 6 | return ( 7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 |

15 | A blockchain-based collection of casino games 16 |

17 | 18 | 19 | Play Blackjack ♣️ 20 | 21 | 22 | Play Slots 🎰 23 | 24 | 25 | Play Roulette 🎲 26 | 27 |
28 | 29 | 30 |
31 | ); 32 | }; 33 | 34 | export default LandingPage; 35 | -------------------------------------------------------------------------------- /frontend/src/BlackJack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BlackJack Prototype 7 | 8 | 9 | 10 |

CryptoCasino: Blackjack

11 |
12 |
13 |

Dealer's Hand:

14 | 15 |
16 |
17 |
18 | 19 | 20 |
21 |
22 |
23 |

Your Hand:

24 | 25 |
26 |
27 |
28 |

Results:

29 |
30 |
31 | 32 |
33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /frontend/src/App.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Righteous&display=swap"); 2 | 3 | body { 4 | background-color: rgb(247, 247, 255); 5 | } 6 | 7 | td { 8 | cursor: pointer; 9 | } 10 | 11 | .brand { 12 | font-family: "Righteous", cursive; 13 | } 14 | 15 | .landing-page-image-container { 16 | width: 18rem; 17 | margin: 0 auto; 18 | } 19 | 20 | .landing-page-image { 21 | width: 100%; 22 | } 23 | 24 | .landing-page-title { 25 | color: rgb(39, 154, 241); 26 | font-family: "Righteous", cursive; 27 | font-size: 1.5rem; 28 | margin-bottom: 1rem; 29 | } 30 | 31 | .bet { 32 | color: black; 33 | display: inline; 34 | margin-right: 1rem; 35 | font-weight: bold; 36 | } 37 | 38 | .old-result { 39 | color: white; 40 | padding: 0.5rem; 41 | border-radius: 5px; 42 | width: 40px; 43 | text-align: center; 44 | display: inline; 45 | margin-right: 1rem; 46 | font-weight: bold; 47 | } 48 | 49 | /* sm */ 50 | @media (min-width: 576px) { 51 | .landing-page-image-container { 52 | width: 24rem; 53 | } 54 | } 55 | 56 | /* md */ 57 | @media (min-width: 768px) { 58 | } 59 | 60 | /* lg */ 61 | @media (min-width: 992px) { 62 | .landing-page-image-container { 63 | width: 30rem; 64 | } 65 | } 66 | 67 | /* xl */ 68 | @media (min-width: 1200px) { 69 | .landing-page-image-container { 70 | width: 35rem; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /frontend/src/utils/connectors.ts: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | Copyright (c) 2022 ChainShot 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 4 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 5 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 9 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | */ 11 | 12 | import { InjectedConnector } from '@web3-react/injected-connector'; 13 | 14 | // 80001 = Matic Mumbai Testnet 15 | // 31337/1337 = Localhost Testnet 16 | export const injected = new InjectedConnector({ 17 | supportedChainIds: [80001, 31337, 1337] 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/src/hooks/useRoulette.ts: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | export const useRoulette = () => { 4 | const [straightUps, setStraightUps] = useState([ 5 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 | ]); // 36 straight up numbers 8 | const [zeros, setZeros] = useState([0, 0]); // 0 - 00 9 | const [columns, setColumns] = useState([0, 0, 0]); 10 | const [dozens, setDozens] = useState([0, 0, 0]); // 1_12 - 13_24 - 25_36 11 | const [redBlack, setRedBlack] = useState([0, 0]); // red - black 12 | const [oddEven, setOddEven] = useState([0, 0]); // odd - even 13 | const [highLow, setHighLow] = useState([0, 0]); // 1_18 - 19_36 14 | 15 | const clear = () => { 16 | setStraightUps([ 17 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19 | ]); 20 | setZeros([0, 0]); 21 | setColumns([0, 0, 0]); 22 | setDozens([0, 0, 0]); 23 | setRedBlack([0, 0]); 24 | setOddEven([0, 0]); 25 | setHighLow([0, 0]); 26 | }; 27 | 28 | return { 29 | straightUps, 30 | setStraightUps, 31 | zeros, 32 | setZeros, 33 | columns, 34 | setColumns, 35 | dozens, 36 | setDozens, 37 | redBlack, 38 | setRedBlack, 39 | oddEven, 40 | setOddEven, 41 | highLow, 42 | setHighLow, 43 | clear, 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /frontend/src/utils/provider.ts: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | Copyright (c) 2022 ChainShot 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 4 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 5 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 8 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 9 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | */ 11 | 12 | import type { Web3Provider as ProviderType } from '@ethersproject/providers'; 13 | import { Web3Provider } from '@ethersproject/providers'; 14 | 15 | export function getProvider(provider: any): ProviderType { 16 | const web3Provider = new Web3Provider(provider); 17 | web3Provider.pollingInterval = 1000; 18 | return web3Provider; 19 | } 20 | 21 | export type Provider = ProviderType; 22 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.2", 7 | "@testing-library/react": "^12.1.2", 8 | "@testing-library/user-event": "^13.5.0", 9 | "@types/jest": "^27.4.0", 10 | "@types/node": "^16.11.25", 11 | "@types/react": "^17.0.39", 12 | "@types/react-dom": "^17.0.11", 13 | "@types/react-router-dom": "^5.3.3", 14 | "@web3-react/abstract-connector": "^6.0.7", 15 | "@web3-react/core": "^6.1.9", 16 | "@web3-react/injected-connector": "^6.0.7", 17 | "bootstrap": "^5.1.3", 18 | "ethers": "^5.6.4", 19 | "joi": "^17.6.0", 20 | "react": "^17.0.2", 21 | "react-bootstrap": "^2.2.0", 22 | "react-custom-roulette": "^1.2.0", 23 | "react-dom": "^17.0.2", 24 | "react-free-playing-cards": "^0.4.2", 25 | "react-router-dom": "^6.2.2", 26 | "react-scripts": "5.0.0", 27 | "typescript": "^4.5.5", 28 | "web-vitals": "^2.1.4" 29 | }, 30 | "scripts": { 31 | "start": "react-scripts start", 32 | "build": "react-scripts build", 33 | "test": "react-scripts test", 34 | "eject": "react-scripts eject" 35 | }, 36 | "eslintConfig": { 37 | "extends": [ 38 | "react-app", 39 | "react-app/jest" 40 | ] 41 | }, 42 | "browserslist": { 43 | "production": [ 44 | ">0.2%", 45 | "not dead", 46 | "not op_mini all" 47 | ], 48 | "development": [ 49 | "last 1 chrome version", 50 | "last 1 firefox version", 51 | "last 1 safari version" 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from "dotenv"; 2 | 3 | import { HardhatUserConfig, task } from "hardhat/config"; 4 | import "@nomiclabs/hardhat-etherscan"; 5 | import "@nomiclabs/hardhat-waffle"; 6 | import "@typechain/hardhat"; 7 | import "hardhat-gas-reporter"; 8 | import "solidity-coverage"; 9 | 10 | dotenv.config(); 11 | 12 | // This is a sample Hardhat task. To learn how to create your own go to 13 | // https://hardhat.org/guides/create-task.html 14 | task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { 15 | const accounts = await hre.ethers.getSigners(); 16 | 17 | for (const account of accounts) { 18 | console.log(account.address); 19 | } 20 | }); 21 | 22 | // You need to export an object to set up your config 23 | // Go to https://hardhat.org/config/ to learn more 24 | 25 | const config: HardhatUserConfig = { 26 | solidity: { 27 | version: "0.8.4", 28 | settings: { 29 | optimizer: { 30 | enabled: true, 31 | runs: 1000 32 | }, 33 | } 34 | }, 35 | paths: { 36 | artifacts: './frontend/src/artifacts' 37 | }, 38 | networks: { 39 | matic: { 40 | url: "https://rpc-mumbai.maticvigil.com", 41 | accounts: process.env.MUMBAI_PRIVATE_KEY !== undefined ? [process.env.MUMBAI_PRIVATE_KEY] : [], 42 | }, 43 | }, 44 | gasReporter: { 45 | enabled: process.env.REPORT_GAS !== undefined, 46 | currency: "USD", 47 | }, 48 | etherscan: { 49 | apiKey: process.env.ETHERSCAN_API_KEY, 50 | }, 51 | }; 52 | 53 | export default config; 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blockchaingame", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/jweiss0/BlockchainGame.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/jweiss0/BlockchainGame/issues" 18 | }, 19 | "homepage": "https://github.com/jweiss0/BlockchainGame#readme", 20 | "devDependencies": { 21 | "@nomiclabs/hardhat-ethers": "^2.0.5", 22 | "@nomiclabs/hardhat-etherscan": "^3.0.1", 23 | "@nomiclabs/hardhat-waffle": "^2.0.2", 24 | "@typechain/ethers-v5": "^7.2.0", 25 | "@typechain/hardhat": "^2.3.1", 26 | "@types/chai": "^4.3.0", 27 | "@types/mocha": "^9.1.0", 28 | "@types/node": "^12.20.46", 29 | "@typescript-eslint/eslint-plugin": "^4.33.0", 30 | "@typescript-eslint/parser": "^4.33.0", 31 | "chai": "^4.3.6", 32 | "dotenv": "^10.0.0", 33 | "eslint": "^7.32.0", 34 | "eslint-config-prettier": "^8.3.0", 35 | "eslint-config-standard": "^16.0.3", 36 | "eslint-plugin-import": "^2.25.4", 37 | "eslint-plugin-node": "^11.1.0", 38 | "eslint-plugin-prettier": "^3.4.1", 39 | "eslint-plugin-promise": "^5.2.0", 40 | "ethereum-waffle": "^3.4.0", 41 | "ethers": "^5.5.4", 42 | "hardhat": "^2.8.4", 43 | "hardhat-gas-reporter": "^1.0.7", 44 | "prettier": "^2.5.1", 45 | "prettier-plugin-solidity": "^1.0.0-beta.13", 46 | "solhint": "^3.3.7", 47 | "solidity-coverage": "^0.7.19", 48 | "ts-node": "^10.5.0", 49 | "typechain": "^5.2.0", 50 | "typescript": "^4.5.5" 51 | }, 52 | "dependencies": { 53 | "@openzeppelin/contracts": "^4.5.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /test/index.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { ethers } from "hardhat"; 3 | import { Contract } from 'ethers'; 4 | 5 | describe("Deployment", function () { 6 | let dChip: Contract; 7 | let dCasino: Contract; 8 | let dBlackjack: Contract; 9 | let dRoulette: Contract; 10 | 11 | beforeEach(async () => { 12 | // Deploy Chip contract 13 | const fChip = await ethers.getContractFactory("Chip"); 14 | dChip = await fChip.deploy(); 15 | await dChip.deployed(); 16 | // Deploy Casino contract 17 | const fCasino = await ethers.getContractFactory("Casino"); 18 | dCasino = await fCasino.deploy(); 19 | await dCasino.deployed(); 20 | // Deploy Blackjack contract with minbet of 1, maxbet of 500, num decks 4 21 | const fBlackjack = await ethers.getContractFactory("Blackjack"); 22 | dBlackjack = await fBlackjack.deploy(ethers.utils.parseEther("1"), ethers.utils.parseEther("50"), 4); // minbet 1 in wei, maxbet 50 in wei 23 | await dBlackjack.deployed(); 24 | // Deploy Roulette contract with minbet of 1, maxbet of 500, num decks 4 25 | const fRoulette = await ethers.getContractFactory("Roulette"); 26 | dRoulette = await fRoulette.deploy(ethers.utils.parseEther("1"), ethers.utils.parseEther("50")); // minbet 1 in wei, maxbet 50 in wei 27 | await dRoulette.deployed(); 28 | }); 29 | 30 | it("Should successfully set initial contract values", async function () { 31 | // Set values in Chip contract 32 | await dChip.setCasinoAddress(dCasino.address); 33 | // Set values in Casino contract 34 | await dCasino.setChipContractAddress(dChip.address); 35 | await dCasino.addCasinoGameContractAddress(dBlackjack.address); 36 | // Set values in Blackjack (CasinoGame) contract 37 | await dBlackjack.setCasinoContractAddress(dCasino.address); 38 | await dBlackjack.setChipContractAddress(dChip.address); 39 | // Set values in Roulette (CasinoGame) contract 40 | await dRoulette.setCasinoContractAddress(dCasino.address); 41 | await dRoulette.setChipContractAddress(dChip.address); 42 | }); 43 | }); -------------------------------------------------------------------------------- /contracts/Chip.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL v3.0 2 | pragma solidity ^0.8.4; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | /* The Chip contract defines a utility token used for all transactions 8 | * within the Casino games. There is no intention of providing any liquidity 9 | * or monetary value to the Chip token. 10 | */ 11 | contract Chip is ERC20, Ownable { 12 | 13 | // State variables. 14 | address private casinoAddress; 15 | 16 | constructor() ERC20("Chip", "CHIP") {} 17 | 18 | // Modifier to check if the calling address is the Casino contract address. 19 | modifier onlyCasino { 20 | require(msg.sender == casinoAddress, "Caller must be Casino."); 21 | _; 22 | } 23 | 24 | // Set the address of the Casino contract. 25 | function setCasinoAddress(address _addr) external onlyOwner { 26 | casinoAddress = _addr; 27 | } 28 | 29 | // Getters 30 | function getCasinoAddress() public view returns (address) {return casinoAddress;} 31 | 32 | // Minting function available only to the deploying address. 33 | function mint(address to, uint256 amount) public onlyOwner { 34 | _mint(to, amount); 35 | } 36 | 37 | // Minting function available only to the Casino contract address. 38 | function casinoMint(address to, uint256 amount) external onlyCasino { 39 | _mint(to, amount * 10 ** decimals()); // Converts to wei 40 | } 41 | 42 | // Allows the Casino contract to transfer tokens from a user to the contract. 43 | // Also allows for the transfer of tokens from the contract to a user. 44 | function casinoTransferFrom(address _from, address _to, uint256 _value) external onlyCasino { 45 | transferFrom(_from, _to, _value); 46 | } 47 | 48 | // Allows the Casino contract to transfer tokens (pay out) to a user from the contract. 49 | function casinoPayout(address _from, address _to, uint256 _value) external onlyCasino { 50 | increaseAllowance(_from, _value); 51 | transferFrom(_from, _to, _value); 52 | } 53 | } -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | -------------------------------------------------------------------------------- /frontend/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts/Casino.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL v3.0 2 | pragma solidity ^0.8.4; 3 | 4 | import "@openzeppelin/contracts/access/Ownable.sol"; 5 | 6 | interface ChipInterface { 7 | function balanceOf(address account) external view returns (uint256); 8 | function casinoMint(address to, uint256 amount) external; 9 | function casinoTransferFrom(address _from, address _to, uint256 _value) external; 10 | function casinoPayout(address _from, address _to, uint256 _value) external; 11 | } 12 | 13 | /* The Casino contract defines top-level Casino-related transactions that occur 14 | * within the casino. The main purpose for this contract is to provide a way 15 | * for users to claim free utility tokens to use for the casino games, almost 16 | * like a "chip exchange". 17 | */ 18 | contract Casino is Ownable { 19 | 20 | // State variables 21 | ChipInterface private chipContract; 22 | // address private deployerAddress; 23 | address[] private casinoGameAddresses; 24 | mapping (address => bool) private freeTokensClaimed; 25 | 26 | // Modifier to check if the calling address is a CasinoGame contract address 27 | modifier onlyCasinoGame { 28 | bool isAddr = false; 29 | for(uint i = 0; i < casinoGameAddresses.length; i++) { 30 | if(msg.sender == casinoGameAddresses[i]) { 31 | isAddr = true; 32 | break; 33 | } 34 | } 35 | require(isAddr, "Caller must be CasinoGame."); 36 | _; 37 | } 38 | 39 | // Sets the address of the Chip utility token contract 40 | function setChipContractAddress(address _address) external onlyOwner { 41 | chipContract = ChipInterface(_address); 42 | } 43 | 44 | // Add address of CasinoGame 45 | function addCasinoGameContractAddress(address _address) external onlyOwner { 46 | casinoGameAddresses.push(_address); 47 | } 48 | 49 | // Checks if a user has already claimed free utility tokens 50 | function alreadyClaimedTokens(address _address) external view returns (bool) { 51 | return freeTokensClaimed[_address]; 52 | } 53 | 54 | // Allows a user to claim 100 free utility tokens one time 55 | function claimInitialTokens() external { 56 | // Check that the user has not already claimed their free tokens 57 | require(freeTokensClaimed[msg.sender] == false, "Already claimed free tokens."); 58 | // Mint the tokens for the user using the Casino contract function 59 | chipContract.casinoMint(msg.sender, 100); 60 | // Mark the user's first time chips as claimed 61 | freeTokensClaimed[msg.sender] = true; 62 | } 63 | 64 | // Pays a certain amount of winnings to the specified address. If the Casino 65 | // contract does not have enough Chips, more are minted for the Casino. 66 | function payWinnings(address _to, uint256 _amount) external onlyCasinoGame { 67 | if(chipContract.balanceOf(address(this)) <= _amount) { 68 | chipContract.casinoMint(address(this), _amount * 10); 69 | } 70 | chipContract.casinoPayout(address(this), _to, _amount); 71 | } 72 | 73 | // Takes a certain amount from the paying wallet and transfers it to 74 | // the casino contract. 75 | function transferFrom(address _from, uint256 _amount) external onlyCasinoGame { 76 | chipContract.casinoTransferFrom(_from, address(this), _amount); 77 | } 78 | } -------------------------------------------------------------------------------- /scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | // We require the Hardhat Runtime Environment explicitly here. This is optional 2 | // but useful for running the script in a standalone fashion through `node