diff --git a/packages/hardhat/deployments/ten/FootballGame.json b/packages/hardhat/deployments/ten/FootballGame.json index 175fe3b..3dc0c8e 100644 --- a/packages/hardhat/deployments/ten/FootballGame.json +++ b/packages/hardhat/deployments/ten/FootballGame.json @@ -1,5 +1,5 @@ { - "address": "0x492bD2595393678F4E7ef2a2D3136860D4d83378", + "address": "0x0238E08bFCd6252c70c3A1C30eeD44D70fe53156", "abi": [ { "inputs": [ @@ -29,7 +29,13 @@ { "indexed": true, "internalType": "address", - "name": "opponent", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", "type": "address" }, { @@ -56,6 +62,18 @@ "internalType": "uint256", "name": "gameId", "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" } ], "name": "GameFinished", @@ -69,6 +87,18 @@ "internalType": "uint256", "name": "gameId", "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" } ], "name": "GameFinishedByTimelock", @@ -86,13 +116,13 @@ { "indexed": true, "internalType": "address", - "name": "challenger", + "name": "sender", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "opponent", + "name": "recipient", "type": "address" }, { @@ -501,19 +531,19 @@ "type": "function" } ], - "transactionHash": "0x651f86c420c77861bccc9e1f36eff6dcfaa3af4387fd0c0b9aa02c9402667c29", + "transactionHash": "0x26a6ed5d4f8884e4ca387d0492037ab412689e1a8480129a0976ccd0ac9ae1af", "receipt": { "to": null, "from": null, - "contractAddress": "0x492bD2595393678F4E7ef2a2D3136860D4d83378", + "contractAddress": "0x0238E08bFCd6252c70c3A1C30eeD44D70fe53156", "transactionIndex": 0, - "gasUsed": "1573074", + "gasUsed": "1582389", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0b2dca281cfc807fd9dd7829eaa1d7ba7290d55bbd1143c4132d1d2769b608cf", - "transactionHash": "0x651f86c420c77861bccc9e1f36eff6dcfaa3af4387fd0c0b9aa02c9402667c29", + "blockHash": "0xb2beaaf86df3d7d9e5fde59f8dc71e3f5305169b9087bf09f03fa579afbec493", + "transactionHash": "0x26a6ed5d4f8884e4ca387d0492037ab412689e1a8480129a0976ccd0ac9ae1af", "logs": [], - "blockNumber": 79787, - "cumulativeGasUsed": "1573074", + "blockNumber": 80042, + "cumulativeGasUsed": "1582389", "status": 1, "byzantium": true }, @@ -521,11 +551,11 @@ "0x479a15a13358561c3fe9B982b69c3da191aB4F92", 100 ], - "numDeployments": 9, - "solcInputHash": "001046b1511190b5dbe14a75c819fb33", - "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_footballCoin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_timelockBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GameAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"GameFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"GameFinishedByTimelock\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GameProposed\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"formation\",\"type\":\"uint256[]\"}],\"name\":\"acceptGame\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"playerId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"teamId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"attack\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"defense\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"speed\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"power\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"stamina\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"technique\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"goalkeeping\",\"type\":\"uint128\"}],\"name\":\"addPlayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfValues\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"prevRandao\",\"type\":\"bytes32\"}],\"name\":\"extractRandomValues\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"footballCoin\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"gameResults\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"goalsHomeTeam\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"goalsAwayTeam\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"games\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isFinished\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"goalsHomeTeam\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"goalsAwayTeam\",\"type\":\"uint256\"}],\"internalType\":\"struct FootballGame.GameResult\",\"name\":\"result\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"getGameResult\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"goalsHomeTeam\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"goalsAwayTeam\",\"type\":\"uint256\"}],\"internalType\":\"struct FootballGame.GameResult\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"opponentClaimTimelock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"players\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"player_id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"team_id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"attack\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"defense\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"speed\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"power\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"stamina\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"technique\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"goalkeeping\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"formation\",\"type\":\"uint256[]\"}],\"name\":\"proposeGame\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"revealOutcome\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timelockBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FootballGame.sol\":\"FootballGame\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"contracts/FootballGame.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract FootballGame {\\n\\taddress public owner;\\n\\tIERC20 public footballCoin;\\n\\tuint public timelockBlocks;\\n\\n\\tstruct Game {\\n\\t\\taddress challenger;\\n\\t\\taddress opponent;\\n\\t\\tuint256 wagerAmount;\\n\\t\\tuint256[] challengerFormation;\\n\\t\\tuint256[] opponentFormation;\\n\\t\\tbool isFinished;\\n\\t\\tGameResult result;\\n\\t\\tuint blockNumber;\\n\\t}\\n\\n\\tstruct GameResult {\\n\\t\\tuint goalsHomeTeam;\\n\\t\\tuint goalsAwayTeam;\\n\\t}\\n\\n\\t///////////////\\n\\t// MAPPINGS //\\n\\t///////////////\\n\\n\\tmapping(uint256 => uint256[]) private challenger_formation;\\n\\tmapping(uint256 => Game) public games;\\n\\tmapping(uint256 => GameResult) public gameResults;\\n\\tuint256 public gameCount;\\n\\n\\tfunction getGameResult(\\n\\t\\tuint256 gameId\\n\\t) public view returns (GameResult memory) {\\n\\t\\treturn gameResults[gameId];\\n\\t}\\n\\n\\tfunction getGameCount() public view returns (uint256) {\\n\\t\\treturn gameCount;\\n\\t}\\n\\n\\t///////////////\\n\\t// EVENTS //\\n\\t///////////////\\n\\n\\tevent GameProposed(\\n\\t\\tuint256 gameId,\\n\\t\\taddress indexed challenger,\\n\\t\\taddress indexed opponent,\\n\\t\\tuint256 wagerAmount,\\n\\t\\tuint blockNumber\\n\\t);\\n\\n\\tevent GameAccepted(\\n\\t\\tuint256 gameId,\\n\\t\\taddress indexed opponent,\\n\\t\\tuint256 wagerAmount,\\n\\t\\tuint blockNumber\\n\\t);\\n\\n\\tevent GameFinished(uint256 gameId);\\n\\n\\tevent GameFinishedByTimelock(uint256 gameId);\\n\\n\\t///////////////\\n\\t// PLAYERS //\\n\\t///////////////\\n\\n\\tstruct Player {\\n\\t\\tuint256 player_id;\\n\\t\\tuint256 team_id;\\n\\t\\tuint256 position; // 0 = Empty, 1 = Goalkeeper, 2 = Defense, 3 = Midfield, 4 = Attack\\n\\t\\tuint128 attack;\\n\\t\\tuint128 defense;\\n\\t\\tuint128 speed;\\n\\t\\tuint128 power;\\n\\t\\tuint128 stamina;\\n\\t\\tuint128 technique;\\n\\t\\tuint128 goalkeeping;\\n\\t}\\n\\n\\tmapping(uint256 => Player) public players;\\n\\n\\tfunction addPlayer(\\n\\t\\tuint256 playerId,\\n\\t\\tuint256 teamId,\\n\\t\\tuint256 position,\\n\\t\\tuint128 attack,\\n\\t\\tuint128 defense,\\n\\t\\tuint128 speed,\\n\\t\\tuint128 power,\\n\\t\\tuint128 stamina,\\n\\t\\tuint128 technique,\\n\\t\\tuint128 goalkeeping\\n\\t) public onlyOwner {\\n\\t\\tPlayer memory newPlayer = Player({\\n\\t\\t\\tplayer_id: playerId,\\n\\t\\t\\tteam_id: teamId,\\n\\t\\t\\tposition: position,\\n\\t\\t\\tattack: attack,\\n\\t\\t\\tdefense: defense,\\n\\t\\t\\tspeed: speed,\\n\\t\\t\\tpower: power,\\n\\t\\t\\tstamina: stamina,\\n\\t\\t\\ttechnique: technique,\\n\\t\\t\\tgoalkeeping: goalkeeping\\n\\t\\t});\\n\\n\\t\\tplayers[playerId] = newPlayer;\\n\\t}\\n\\n\\t///////////////\\n\\t// CONSTRUCTOR //\\n\\t///////////////\\n\\n\\tconstructor(IERC20 _footballCoin, uint _timelockBlocks) {\\n\\t\\towner = msg.sender;\\n\\t\\tfootballCoin = _footballCoin;\\n\\t\\ttimelockBlocks = _timelockBlocks;\\n\\t}\\n\\tmodifier onlyOwner() {\\n\\t\\trequire(msg.sender == owner, \\\"Caller is not the owner\\\");\\n\\t\\t_;\\n\\t}\\n\\n\\t///////////////\\n\\t// GAME FUNCTIONS //\\n\\t///////////////\\n\\n\\tfunction proposeGame(\\n\\t\\taddress opponent,\\n\\t\\tuint256 wagerAmount,\\n\\t\\tuint256[] memory formation\\n\\t) public {\\n\\t\\trequire(\\n\\t\\t\\tfootballCoin.allowance(msg.sender, address(this)) >= wagerAmount,\\n\\t\\t\\t\\\"Insufficient allowance for wager\\\"\\n\\t\\t);\\n\\t\\tfor (uint i = 0; i < formation.length; i++) {\\n\\t\\t\\trequire(players[formation[i]].player_id != 0, \\\"Invalid player id\\\");\\n\\t\\t}\\n\\n\\t\\t// Transfer the wager amount from the challenger to the contract\\n\\t\\tfootballCoin.transferFrom(msg.sender, address(this), wagerAmount);\\n\\n\\t\\tuint256 newGameId = ++gameCount;\\n\\t\\tgames[newGameId] = Game({\\n\\t\\t\\tchallenger: msg.sender,\\n\\t\\t\\topponent: opponent,\\n\\t\\t\\twagerAmount: wagerAmount,\\n\\t\\t\\tchallengerFormation: new uint256[](0),\\n\\t\\t\\topponentFormation: new uint256[](0),\\n\\t\\t\\tisFinished: false,\\n\\t\\t\\tresult: GameResult({ goalsHomeTeam: 0, goalsAwayTeam: 0 }),\\n\\t\\t\\tblockNumber: block.number\\n\\t\\t});\\n\\n\\t\\tchallenger_formation[newGameId] = formation;\\n\\n\\t\\t// Emitting events to notify about the new game proposal\\n\\t\\temit GameProposed(\\n\\t\\t\\tnewGameId,\\n\\t\\t\\tmsg.sender,\\n\\t\\t\\topponent,\\n\\t\\t\\twagerAmount,\\n\\t\\t\\tblock.number\\n\\t\\t);\\n\\t}\\n\\n\\tfunction acceptGame(uint256 gameId, uint256[] memory formation) public {\\n\\t\\tGame storage game = games[gameId];\\n\\n\\t\\trequire(\\n\\t\\t\\tmsg.sender == game.opponent,\\n\\t\\t\\t\\\"Only the opponent can accept the game\\\"\\n\\t\\t);\\n\\t\\trequire(\\n\\t\\t\\tfootballCoin.allowance(msg.sender, address(this)) >=\\n\\t\\t\\t\\tgame.wagerAmount,\\n\\t\\t\\t\\\"Insufficient allowance for wager\\\"\\n\\t\\t);\\n\\t\\tfor (uint i = 0; i < formation.length; i++) {\\n\\t\\t\\trequire(players[formation[i]].player_id != 0, \\\"Invalid player id\\\");\\n\\t\\t}\\n\\n\\t\\t// Transfer the wager amount from the opponent to the contract\\n\\t\\tfootballCoin.transferFrom(msg.sender, address(this), game.wagerAmount);\\n\\n\\t\\tgame.opponentFormation = formation;\\n\\t\\tgame.blockNumber = block.number;\\n\\n\\t\\t// Notify about game acceptance\\n\\t\\temit GameAccepted(gameId, msg.sender, game.wagerAmount, block.number);\\n\\t}\\n\\n\\tfunction revealOutcome(uint256 gameId) public {\\n\\t\\tGame storage game = games[gameId];\\n\\n\\t\\trequire(\\n\\t\\t\\tmsg.sender == game.challenger,\\n\\t\\t\\t\\\"Only the challenger can reveal the outcome\\\"\\n\\t\\t);\\n\\t\\trequire(!game.isFinished, \\\"The game is already finished\\\");\\n\\n\\t\\tgame.challengerFormation = challenger_formation[gameId];\\n\\n\\t\\tGameResult memory result = determineGameResult(game);\\n\\t\\tgameResults[gameId] = result;\\n\\n\\t\\tgame.isFinished = true;\\n\\n\\t\\taddress winner = determineWinner(game, result);\\n\\t\\tpayoutWinners(game, winner);\\n\\n\\t\\temit GameFinished(gameId);\\n\\t}\\n\\n\\tfunction opponentClaimTimelock(uint256 gameId) public {\\n\\t\\tGame storage game = games[gameId];\\n\\n\\t\\trequire(\\n\\t\\t\\tmsg.sender == game.opponent,\\n\\t\\t\\t\\\"Only the opponent can claim the timelock\\\"\\n\\t\\t);\\n\\t\\trequire(\\n\\t\\t\\tblock.number > game.blockNumber + timelockBlocks,\\n\\t\\t\\t\\\"Opponent can claim timelock only after timelockBlocks have passed\\\"\\n\\t\\t);\\n\\n\\t\\tgame.isFinished = true;\\n\\t\\tpayoutWinners(game, game.opponent);\\n\\n\\t\\temit GameFinishedByTimelock(gameId);\\n\\t}\\n\\n\\t///////////////\\n\\t// HELPER FUNCTIONS //\\n\\t///////////////\\n\\n\\tfunction determineGameResult(\\n\\t\\tGame storage game\\n\\t) private view returns (GameResult memory) {\\n\\t\\tGameResult memory result = GameResult({\\n\\t\\t\\tgoalsHomeTeam: 0,\\n\\t\\t\\tgoalsAwayTeam: 0\\n\\t\\t});\\n\\n\\t\\t// Player memory homeGoalkeeper = players[game.challengerFormation[1]];\\n\\t\\t// Player memory awayGoalkeeper = players[game.opponentFormation[1]];\\n\\t\\tbytes32 prevRandao = blockhash(block.number - 1);\\n\\t\\tuint256[] memory randomValues = extractRandomValues(10, prevRandao);\\n\\t\\tfor (uint i = 1; i < game.challengerFormation.length; i++) {\\n\\t\\t\\tPlayer memory homePlayer = players[game.challengerFormation[i]];\\n\\t\\t\\tPlayer memory awayPlayer = players[\\n\\t\\t\\t\\tgame.opponentFormation[game.challengerFormation.length - i]\\n\\t\\t\\t];\\n\\t\\t\\tuint256 totalspeed = homePlayer.speed + awayPlayer.speed;\\n\\t\\t\\tuint256 randomSpeed = uint256(prevRandao) % totalspeed;\\n\\t\\t\\tif (homePlayer.speed > randomSpeed) {\\n\\t\\t\\t\\t// Home player attacks\\n\\t\\t\\t\\tif (homePlayer.attack > randomValues[i - 1]) {\\n\\t\\t\\t\\t\\tresult.goalsHomeTeam++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (awayPlayer.attack > randomValues[i - 1]) {\\n\\t\\t\\t\\t\\tresult.goalsAwayTeam++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\treturn result;\\n\\t}\\n\\n\\tfunction extractRandomValues(\\n\\t\\tuint numberOfValues,\\n\\t\\tbytes32 prevRandao\\n\\t) public pure returns (uint[] memory) {\\n\\t\\trequire(numberOfValues > 0, \\\"Number of values must be greater than 0\\\");\\n\\t\\tuint[] memory randomValues = new uint[](numberOfValues);\\n\\t\\tuint256 randValue = uint256(prevRandao);\\n\\n\\t\\tfor (uint i = 0; i < numberOfValues; i++) {\\n\\t\\t\\trandomValues[i] = randValue % 100;\\n\\t\\t\\trandValue = randValue / 256; // Shift right by 2 hex digits\\n\\t\\t}\\n\\n\\t\\treturn randomValues;\\n\\t}\\n\\n\\tfunction determineWinner(\\n\\t\\tGame storage game,\\n\\t\\tGameResult memory result\\n\\t) private view returns (address) {\\n\\t\\tif (result.goalsHomeTeam > result.goalsAwayTeam) {\\n\\t\\t\\treturn game.challenger;\\n\\t\\t} else if (result.goalsHomeTeam < result.goalsAwayTeam) {\\n\\t\\t\\treturn game.opponent;\\n\\t\\t}\\n\\t\\treturn address(0); // It's a draw\\n\\t}\\n\\n\\tfunction payoutWinners(Game storage game, address winner) private {\\n\\t\\tif (winner == address(0)) {\\n\\t\\t\\trequire(\\n\\t\\t\\t\\tfootballCoin.transfer(game.challenger, game.wagerAmount),\\n\\t\\t\\t\\t\\\"Transfer to challenger failed\\\"\\n\\t\\t\\t);\\n\\t\\t\\trequire(\\n\\t\\t\\t\\tfootballCoin.transfer(game.opponent, game.wagerAmount),\\n\\t\\t\\t\\t\\\"Transfer to opponent failed\\\"\\n\\t\\t\\t);\\n\\t\\t} else {\\n\\t\\t\\tuint256 totalPot = game.wagerAmount * 2;\\n\\t\\t\\trequire(\\n\\t\\t\\t\\tfootballCoin.transfer(winner, totalPot),\\n\\t\\t\\t\\t\\\"Transfer to winner failed\\\"\\n\\t\\t\\t);\\n\\t\\t}\\n\\t}\\n}\\n\",\"keccak256\":\"0x43a3c9ba443f724de81ad8efebc8e97a28d0d970564f289c337b7991cd915280\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50604051611aea380380611aea83398101604081905261002f91610066565b60008054336001600160a01b031991821617909155600180549091166001600160a01b0393909316929092179091556002556100a0565b6000806040838503121561007957600080fd5b82516001600160a01b038116811461009057600080fd5b6020939093015192949293505050565b611a3b806100af6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806394b1e59511610097578063ed2df26d11610066578063ed2df26d1461025d578063f71d96cb146102b6578063fda0f9a214610386578063fdba1b7c1461038f57600080fd5b806394b1e5951461021c578063cd86f8101461022f578063cfb9479814610242578063e87c0ee61461025557600080fd5b806352bab1c9116100d357806352bab1c9146101ab57806359c892a9146101cb57806364407bad146101de5780638da5cb5b1461020957600080fd5b8063117a5b90146100fa5780634d1975b41461017f578063506d7e2d14610196575b600080fd5b6101646101083660046115d9565b60046020908152600091825260409182902080546001820154600283015460058401548651808801909752600685015487526007850154958701959095526008909301546001600160a01b0392831695919092169360ff169186565b604051610176969594939291906115f2565b60405180910390f35b61018860065481565b604051908152602001610176565b6101a96101a436600461165d565b6103cb565b005b6101be6101b9366004611702565b61051b565b6040516101769190611724565b6101a96101d9366004611819565b610624565b6001546101f1906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b6000546101f1906001600160a01b031681565b6101a961022a3660046115d9565b6108e1565b6101a961023d366004611860565b610a4c565b6101a96102503660046115d9565b610e05565b600654610188565b6102a961026b3660046115d9565b604080518082019091526000808252602082015250600090815260056020908152604091829020825180840190935280548352600101549082015290565b60405161017691906118c5565b6103296102c43660046115d9565b60076020526000908152604090208054600182015460028301546003840154600485015460058601546006909601549495939492936001600160801b0380841694600160801b948590048216948483169481900483169380841693919004811691168a565b604080519a8b5260208b0199909952978901969096526001600160801b039485166060890152928416608088015290831660a0870152821660c0860152811660e08501529081166101008401521661012082015261014001610176565b61018860025481565b6103b661039d3660046115d9565b6005602052600090815260409020805460019091015482565b60408051928352602083019190915201610176565b6000546001600160a01b0316331461042a5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064015b60405180910390fd5b60408051610140810182528b815260208082019b8c528183019a8b526001600160801b03998a1660608301908152988a1660808301908152978a1660a08301908152968a1660c08301908152958a1660e08301908152948a166101008301908152938a16610120830190815260009d8e52600790915291909b209a518b55985160018b0155965160028a015593519251928516600160801b938616840217600389015590519051908416908416820217600487015590519251928216928216029190911760058401559051600690920180546fffffffffffffffffffffffffffffffff191692909116919091179055565b60606000831161057d5760405162461bcd60e51b815260206004820152602760248201527f4e756d626572206f662076616c756573206d75737420626520677265617465726044820152660207468616e20360cc1b6064820152608401610421565b60008367ffffffffffffffff81111561059857610598611768565b6040519080825280602002602001820160405280156105c1578160200160208202803683370190505b5090508260005b85811015610618576105db6064836118f2565b8382815181106105ed576105ed611906565b602090810291909101015261060461010083611932565b91508061061081611946565b9150506105c8565b50909150505b92915050565b600082815260046020526040902060018101546001600160a01b0316331461069c5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c7920746865206f70706f6e656e742063616e20616363657074207468656044820152642067616d6560d81b6064820152608401610421565b6002810154600154604051636eb1769f60e11b81523360048201523060248201526001600160a01b039091169063dd62ed3e90604401602060405180830381865afa1580156106ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610713919061195f565b10156107615760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b82518110156107f2576007600084838151811061078357610783611906565b60200260200101518152602001908152602001600020600001546000036107e05760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b806107ea81611946565b915050610764565b5060015460028201546040516323b872dd60e01b815233600482015230602482015260448101919091526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610850573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108749190611978565b50815161088a9060048301906020850190611539565b504360088201819055600282015460408051868152602081019290925281019190915233907f3e4861c2ee824ef513d4f257f8e91ed935561ba29a3a66edaf6106956b1a33409060600160405180910390a2505050565b600081815260046020526040902060018101546001600160a01b0316331461095c5760405162461bcd60e51b815260206004820152602860248201527f4f6e6c7920746865206f70706f6e656e742063616e20636c61696d207468652060448201526774696d656c6f636b60c01b6064820152608401610421565b600254816008015461096e91906119a1565b43116109ec5760405162461bcd60e51b815260206004820152604160248201527f4f70706f6e656e742063616e20636c61696d2074696d656c6f636b206f6e6c7960448201527f2061667465722074696d656c6f636b426c6f636b7320686176652070617373656064820152601960fa1b608482015260a401610421565b60058101805460ff19166001908117909155810154610a159082906001600160a01b0316610f7e565b6040518281527f3940a261f19a11e745a180d85bc64bb8a1360ea9d291fff0bce0d67cc4261f949060200160405180910390a15050565b600154604051636eb1769f60e11b815233600482015230602482015283916001600160a01b03169063dd62ed3e90604401602060405180830381865afa158015610a9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abe919061195f565b1015610b0c5760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b8151811015610b9d5760076000838381518110610b2e57610b2e611906565b6020026020010151815260200190815260200160002060000154600003610b8b5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b80610b9581611946565b915050610b0f565b506001546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610bf5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c199190611978565b506000600660008154610c2b90611946565b918290555060408051610100810182523381526001600160a01b0387166020820152908101859052909150606081016000604051908082528060200260200182016040528015610c85578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610cb6578160200160208202803683370190505b5081526000602080830182905260408051808201825283815280830184905281850152436060948501528583526004825291829020845181546001600160a01b039182166001600160a01b0319918216178355868401516001840180549190931691161790559184015160028301559183015180519192610d3f92600385019290910190611539565b5060808201518051610d5b916004840191602090910190611539565b5060a082015160058201805460ff191691151591909117905560c082015180516006830155602090810151600783015560e090920151600890910155600082815260038252604090208351610db292850190611539565b506040805182815260208101859052438183015290516001600160a01b0386169133917f02c4c4ed29b388428cf1564d10b179c4153a007fb74269c8cc4681465146f50a9181900360600190a350505050565b600081815260046020526040902080546001600160a01b03163314610e7f5760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c7920746865206368616c6c656e6765722063616e2072657665616c20746044820152696865206f7574636f6d6560b01b6064820152608401610421565b600581015460ff1615610ed45760405162461bcd60e51b815260206004820152601c60248201527f5468652067616d6520697320616c72656164792066696e6973686564000000006044820152606401610421565b60008281526003602081905260409091208054610ef49284019190611584565b506000610f0082611204565b600084815260056020818152604083208451815590840151600191820155908501805460ff19169091179055909150610f3983836114ec565b9050610f458382610f7e565b6040518481527f6543ec12c6e53f26532beb5289ef5732dcd77c2e9e9921ae42b695905f5e84c09060200160405180910390a150505050565b6001600160a01b038116611127576001548254600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af1158015610fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100a9190611978565b6110565760405162461bcd60e51b815260206004820152601d60248201527f5472616e7366657220746f206368616c6c656e676572206661696c65640000006044820152606401610421565b6001805490830154600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af11580156110b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d79190611978565b6111235760405162461bcd60e51b815260206004820152601b60248201527f5472616e7366657220746f206f70706f6e656e74206661696c656400000000006044820152606401610421565b5050565b60008260020154600261113a91906119b4565b60015460405163a9059cbb60e01b81526001600160a01b0385811660048301526024820184905292935091169063a9059cbb906044016020604051808303816000875af115801561118f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b39190611978565b6111ff5760405162461bcd60e51b815260206004820152601960248201527f5472616e7366657220746f2077696e6e6572206661696c6564000000000000006044820152606401610421565b505050565b6040805180820190915260008082526020820152604080518082019091526000808252602082018190526112396001436119cb565b4090506000611249600a8361051b565b905060015b60038601548110156114e25760006007600088600301848154811061127557611275611906565b600091825260208083209091015483528281019390935260409182018120825161014081018452815481526001820154948101949094526002810154928401929092526003808301546001600160801b038082166060870152600160801b918290048116608087015260048086015480831660a0890152839004821660c0880152600586015480831660e08901529290920481166101008701526006909401549093166101208501528a0154929350916007918391908b01906113399087906119cb565b8154811061134957611349611906565b6000918252602080832090910154835282810193909352604091820181208251610140810184528154815260018201549481019490945260028101549284019290925260038201546001600160801b038082166060860152600160801b9182900481166080860152600484015480821660a080880182905291849004831660c0880152600586015480841660e089015293909304821661010087015260069094015416610120850152918501519293509161140491906119de565b6001600160801b03169050600061141b82886118f2565b9050808460a001516001600160801b0316111561147f578561143e6001876119cb565b8151811061144e5761144e611906565b602002602001015184606001516001600160801b0316111561147a5787518861147682611946565b9052505b6114cb565b8561148b6001876119cb565b8151811061149b5761149b611906565b602002602001015183606001516001600160801b031611156114cb57602088018051906114c782611946565b9052505b5050505080806114da90611946565b91505061124e565b5091949350505050565b600081602001518260000151111561150f575081546001600160a01b031661061e565b602082015182511015611530575060018201546001600160a01b031661061e565b50600092915050565b828054828255906000526020600020908101928215611574579160200282015b82811115611574578251825591602001919060010190611559565b506115809291506115c4565b5090565b8280548282559060005260206000209081019282156115745760005260206000209182015b828111156115745782548255916001019190600101906115a9565b5b8082111561158057600081556001016115c5565b6000602082840312156115eb57600080fd5b5035919050565b6001600160a01b0387811682528616602082015260408101859052831515606082015260e08101611630608083018580518252602090810151910152565b8260c0830152979650505050505050565b80356001600160801b038116811461165857600080fd5b919050565b6000806000806000806000806000806101408b8d03121561167d57600080fd5b8a35995060208b0135985060408b0135975061169b60608c01611641565b96506116a960808c01611641565b95506116b760a08c01611641565b94506116c560c08c01611641565b93506116d360e08c01611641565b92506116e26101008c01611641565b91506116f16101208c01611641565b90509295989b9194979a5092959850565b6000806040838503121561171557600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b8181101561175c57835183529284019291840191600101611740565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261178f57600080fd5b8135602067ffffffffffffffff808311156117ac576117ac611768565b8260051b604051601f19603f830116810181811084821117156117d1576117d1611768565b6040529384528581018301938381019250878511156117ef57600080fd5b83870191505b8482101561180e578135835291830191908301906117f5565b979650505050505050565b6000806040838503121561182c57600080fd5b82359150602083013567ffffffffffffffff81111561184a57600080fd5b6118568582860161177e565b9150509250929050565b60008060006060848603121561187557600080fd5b83356001600160a01b038116811461188c57600080fd5b925060208401359150604084013567ffffffffffffffff8111156118af57600080fd5b6118bb8682870161177e565b9150509250925092565b81518152602080830151908201526040810161061e565b634e487b7160e01b600052601260045260246000fd5b600082611901576119016118dc565b500690565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082611941576119416118dc565b500490565b6000600182016119585761195861191c565b5060010190565b60006020828403121561197157600080fd5b5051919050565b60006020828403121561198a57600080fd5b8151801515811461199a57600080fd5b9392505050565b8082018082111561061e5761061e61191c565b808202811582820484141761061e5761061e61191c565b8181038181111561061e5761061e61191c565b6001600160801b038181168382160190808211156119fe576119fe61191c565b509291505056fea2646970667358221220f05846886134de31de3f053bbceaaac71300ed371a3f94b1a3aa2e4fd8fefd9264736f6c63430008110033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806394b1e59511610097578063ed2df26d11610066578063ed2df26d1461025d578063f71d96cb146102b6578063fda0f9a214610386578063fdba1b7c1461038f57600080fd5b806394b1e5951461021c578063cd86f8101461022f578063cfb9479814610242578063e87c0ee61461025557600080fd5b806352bab1c9116100d357806352bab1c9146101ab57806359c892a9146101cb57806364407bad146101de5780638da5cb5b1461020957600080fd5b8063117a5b90146100fa5780634d1975b41461017f578063506d7e2d14610196575b600080fd5b6101646101083660046115d9565b60046020908152600091825260409182902080546001820154600283015460058401548651808801909752600685015487526007850154958701959095526008909301546001600160a01b0392831695919092169360ff169186565b604051610176969594939291906115f2565b60405180910390f35b61018860065481565b604051908152602001610176565b6101a96101a436600461165d565b6103cb565b005b6101be6101b9366004611702565b61051b565b6040516101769190611724565b6101a96101d9366004611819565b610624565b6001546101f1906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b6000546101f1906001600160a01b031681565b6101a961022a3660046115d9565b6108e1565b6101a961023d366004611860565b610a4c565b6101a96102503660046115d9565b610e05565b600654610188565b6102a961026b3660046115d9565b604080518082019091526000808252602082015250600090815260056020908152604091829020825180840190935280548352600101549082015290565b60405161017691906118c5565b6103296102c43660046115d9565b60076020526000908152604090208054600182015460028301546003840154600485015460058601546006909601549495939492936001600160801b0380841694600160801b948590048216948483169481900483169380841693919004811691168a565b604080519a8b5260208b0199909952978901969096526001600160801b039485166060890152928416608088015290831660a0870152821660c0860152811660e08501529081166101008401521661012082015261014001610176565b61018860025481565b6103b661039d3660046115d9565b6005602052600090815260409020805460019091015482565b60408051928352602083019190915201610176565b6000546001600160a01b0316331461042a5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064015b60405180910390fd5b60408051610140810182528b815260208082019b8c528183019a8b526001600160801b03998a1660608301908152988a1660808301908152978a1660a08301908152968a1660c08301908152958a1660e08301908152948a166101008301908152938a16610120830190815260009d8e52600790915291909b209a518b55985160018b0155965160028a015593519251928516600160801b938616840217600389015590519051908416908416820217600487015590519251928216928216029190911760058401559051600690920180546fffffffffffffffffffffffffffffffff191692909116919091179055565b60606000831161057d5760405162461bcd60e51b815260206004820152602760248201527f4e756d626572206f662076616c756573206d75737420626520677265617465726044820152660207468616e20360cc1b6064820152608401610421565b60008367ffffffffffffffff81111561059857610598611768565b6040519080825280602002602001820160405280156105c1578160200160208202803683370190505b5090508260005b85811015610618576105db6064836118f2565b8382815181106105ed576105ed611906565b602090810291909101015261060461010083611932565b91508061061081611946565b9150506105c8565b50909150505b92915050565b600082815260046020526040902060018101546001600160a01b0316331461069c5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c7920746865206f70706f6e656e742063616e20616363657074207468656044820152642067616d6560d81b6064820152608401610421565b6002810154600154604051636eb1769f60e11b81523360048201523060248201526001600160a01b039091169063dd62ed3e90604401602060405180830381865afa1580156106ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610713919061195f565b10156107615760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b82518110156107f2576007600084838151811061078357610783611906565b60200260200101518152602001908152602001600020600001546000036107e05760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b806107ea81611946565b915050610764565b5060015460028201546040516323b872dd60e01b815233600482015230602482015260448101919091526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610850573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108749190611978565b50815161088a9060048301906020850190611539565b504360088201819055600282015460408051868152602081019290925281019190915233907f3e4861c2ee824ef513d4f257f8e91ed935561ba29a3a66edaf6106956b1a33409060600160405180910390a2505050565b600081815260046020526040902060018101546001600160a01b0316331461095c5760405162461bcd60e51b815260206004820152602860248201527f4f6e6c7920746865206f70706f6e656e742063616e20636c61696d207468652060448201526774696d656c6f636b60c01b6064820152608401610421565b600254816008015461096e91906119a1565b43116109ec5760405162461bcd60e51b815260206004820152604160248201527f4f70706f6e656e742063616e20636c61696d2074696d656c6f636b206f6e6c7960448201527f2061667465722074696d656c6f636b426c6f636b7320686176652070617373656064820152601960fa1b608482015260a401610421565b60058101805460ff19166001908117909155810154610a159082906001600160a01b0316610f7e565b6040518281527f3940a261f19a11e745a180d85bc64bb8a1360ea9d291fff0bce0d67cc4261f949060200160405180910390a15050565b600154604051636eb1769f60e11b815233600482015230602482015283916001600160a01b03169063dd62ed3e90604401602060405180830381865afa158015610a9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abe919061195f565b1015610b0c5760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b8151811015610b9d5760076000838381518110610b2e57610b2e611906565b6020026020010151815260200190815260200160002060000154600003610b8b5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b80610b9581611946565b915050610b0f565b506001546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610bf5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c199190611978565b506000600660008154610c2b90611946565b918290555060408051610100810182523381526001600160a01b0387166020820152908101859052909150606081016000604051908082528060200260200182016040528015610c85578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610cb6578160200160208202803683370190505b5081526000602080830182905260408051808201825283815280830184905281850152436060948501528583526004825291829020845181546001600160a01b039182166001600160a01b0319918216178355868401516001840180549190931691161790559184015160028301559183015180519192610d3f92600385019290910190611539565b5060808201518051610d5b916004840191602090910190611539565b5060a082015160058201805460ff191691151591909117905560c082015180516006830155602090810151600783015560e090920151600890910155600082815260038252604090208351610db292850190611539565b506040805182815260208101859052438183015290516001600160a01b0386169133917f02c4c4ed29b388428cf1564d10b179c4153a007fb74269c8cc4681465146f50a9181900360600190a350505050565b600081815260046020526040902080546001600160a01b03163314610e7f5760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c7920746865206368616c6c656e6765722063616e2072657665616c20746044820152696865206f7574636f6d6560b01b6064820152608401610421565b600581015460ff1615610ed45760405162461bcd60e51b815260206004820152601c60248201527f5468652067616d6520697320616c72656164792066696e6973686564000000006044820152606401610421565b60008281526003602081905260409091208054610ef49284019190611584565b506000610f0082611204565b600084815260056020818152604083208451815590840151600191820155908501805460ff19169091179055909150610f3983836114ec565b9050610f458382610f7e565b6040518481527f6543ec12c6e53f26532beb5289ef5732dcd77c2e9e9921ae42b695905f5e84c09060200160405180910390a150505050565b6001600160a01b038116611127576001548254600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af1158015610fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100a9190611978565b6110565760405162461bcd60e51b815260206004820152601d60248201527f5472616e7366657220746f206368616c6c656e676572206661696c65640000006044820152606401610421565b6001805490830154600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af11580156110b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d79190611978565b6111235760405162461bcd60e51b815260206004820152601b60248201527f5472616e7366657220746f206f70706f6e656e74206661696c656400000000006044820152606401610421565b5050565b60008260020154600261113a91906119b4565b60015460405163a9059cbb60e01b81526001600160a01b0385811660048301526024820184905292935091169063a9059cbb906044016020604051808303816000875af115801561118f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b39190611978565b6111ff5760405162461bcd60e51b815260206004820152601960248201527f5472616e7366657220746f2077696e6e6572206661696c6564000000000000006044820152606401610421565b505050565b6040805180820190915260008082526020820152604080518082019091526000808252602082018190526112396001436119cb565b4090506000611249600a8361051b565b905060015b60038601548110156114e25760006007600088600301848154811061127557611275611906565b600091825260208083209091015483528281019390935260409182018120825161014081018452815481526001820154948101949094526002810154928401929092526003808301546001600160801b038082166060870152600160801b918290048116608087015260048086015480831660a0890152839004821660c0880152600586015480831660e08901529290920481166101008701526006909401549093166101208501528a0154929350916007918391908b01906113399087906119cb565b8154811061134957611349611906565b6000918252602080832090910154835282810193909352604091820181208251610140810184528154815260018201549481019490945260028101549284019290925260038201546001600160801b038082166060860152600160801b9182900481166080860152600484015480821660a080880182905291849004831660c0880152600586015480841660e089015293909304821661010087015260069094015416610120850152918501519293509161140491906119de565b6001600160801b03169050600061141b82886118f2565b9050808460a001516001600160801b0316111561147f578561143e6001876119cb565b8151811061144e5761144e611906565b602002602001015184606001516001600160801b0316111561147a5787518861147682611946565b9052505b6114cb565b8561148b6001876119cb565b8151811061149b5761149b611906565b602002602001015183606001516001600160801b031611156114cb57602088018051906114c782611946565b9052505b5050505080806114da90611946565b91505061124e565b5091949350505050565b600081602001518260000151111561150f575081546001600160a01b031661061e565b602082015182511015611530575060018201546001600160a01b031661061e565b50600092915050565b828054828255906000526020600020908101928215611574579160200282015b82811115611574578251825591602001919060010190611559565b506115809291506115c4565b5090565b8280548282559060005260206000209081019282156115745760005260206000209182015b828111156115745782548255916001019190600101906115a9565b5b8082111561158057600081556001016115c5565b6000602082840312156115eb57600080fd5b5035919050565b6001600160a01b0387811682528616602082015260408101859052831515606082015260e08101611630608083018580518252602090810151910152565b8260c0830152979650505050505050565b80356001600160801b038116811461165857600080fd5b919050565b6000806000806000806000806000806101408b8d03121561167d57600080fd5b8a35995060208b0135985060408b0135975061169b60608c01611641565b96506116a960808c01611641565b95506116b760a08c01611641565b94506116c560c08c01611641565b93506116d360e08c01611641565b92506116e26101008c01611641565b91506116f16101208c01611641565b90509295989b9194979a5092959850565b6000806040838503121561171557600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b8181101561175c57835183529284019291840191600101611740565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261178f57600080fd5b8135602067ffffffffffffffff808311156117ac576117ac611768565b8260051b604051601f19603f830116810181811084821117156117d1576117d1611768565b6040529384528581018301938381019250878511156117ef57600080fd5b83870191505b8482101561180e578135835291830191908301906117f5565b979650505050505050565b6000806040838503121561182c57600080fd5b82359150602083013567ffffffffffffffff81111561184a57600080fd5b6118568582860161177e565b9150509250929050565b60008060006060848603121561187557600080fd5b83356001600160a01b038116811461188c57600080fd5b925060208401359150604084013567ffffffffffffffff8111156118af57600080fd5b6118bb8682870161177e565b9150509250925092565b81518152602080830151908201526040810161061e565b634e487b7160e01b600052601260045260246000fd5b600082611901576119016118dc565b500690565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082611941576119416118dc565b500490565b6000600182016119585761195861191c565b5060010190565b60006020828403121561197157600080fd5b5051919050565b60006020828403121561198a57600080fd5b8151801515811461199a57600080fd5b9392505050565b8082018082111561061e5761061e61191c565b808202811582820484141761061e5761061e61191c565b8181038181111561061e5761061e61191c565b6001600160801b038181168382160190808211156119fe576119fe61191c565b509291505056fea2646970667358221220f05846886134de31de3f053bbceaaac71300ed371a3f94b1a3aa2e4fd8fefd9264736f6c63430008110033", + "numDeployments": 10, + "solcInputHash": "28b373b67d70fb99a146639d53e9ea17", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_footballCoin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_timelockBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GameAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"GameFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"GameFinishedByTimelock\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"GameProposed\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"formation\",\"type\":\"uint256[]\"}],\"name\":\"acceptGame\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"playerId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"teamId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"attack\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"defense\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"speed\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"power\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"stamina\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"technique\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"goalkeeping\",\"type\":\"uint128\"}],\"name\":\"addPlayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfValues\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"prevRandao\",\"type\":\"bytes32\"}],\"name\":\"extractRandomValues\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"footballCoin\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"gameResults\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"goalsHomeTeam\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"goalsAwayTeam\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"games\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isFinished\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"goalsHomeTeam\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"goalsAwayTeam\",\"type\":\"uint256\"}],\"internalType\":\"struct FootballGame.GameResult\",\"name\":\"result\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"getGameResult\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"goalsHomeTeam\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"goalsAwayTeam\",\"type\":\"uint256\"}],\"internalType\":\"struct FootballGame.GameResult\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"opponentClaimTimelock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"players\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"player_id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"team_id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"position\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"attack\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"defense\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"speed\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"power\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"stamina\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"technique\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"goalkeeping\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wagerAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"formation\",\"type\":\"uint256[]\"}],\"name\":\"proposeGame\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"}],\"name\":\"revealOutcome\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timelockBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FootballGame.sol\":\"FootballGame\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"contracts/FootballGame.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract FootballGame {\\n\\taddress public owner;\\n\\tIERC20 public footballCoin;\\n\\tuint public timelockBlocks;\\n\\n\\tstruct Game {\\n\\t\\taddress challenger;\\n\\t\\taddress opponent;\\n\\t\\tuint256 wagerAmount;\\n\\t\\tuint256[] challengerFormation;\\n\\t\\tuint256[] opponentFormation;\\n\\t\\tbool isFinished;\\n\\t\\tGameResult result;\\n\\t\\tuint blockNumber;\\n\\t}\\n\\n\\tstruct GameResult {\\n\\t\\tuint goalsHomeTeam;\\n\\t\\tuint goalsAwayTeam;\\n\\t}\\n\\n\\t///////////////\\n\\t// MAPPINGS //\\n\\t///////////////\\n\\n\\tmapping(uint256 => uint256[]) private challenger_formation;\\n\\tmapping(uint256 => Game) public games;\\n\\tmapping(uint256 => GameResult) public gameResults;\\n\\tuint256 public gameCount;\\n\\n\\tfunction getGameResult(\\n\\t\\tuint256 gameId\\n\\t) public view returns (GameResult memory) {\\n\\t\\treturn gameResults[gameId];\\n\\t}\\n\\n\\tfunction getGameCount() public view returns (uint256) {\\n\\t\\treturn gameCount;\\n\\t}\\n\\n\\t///////////////\\n\\t// EVENTS //\\n\\t///////////////\\n\\n\\tevent GameProposed(\\n\\t\\tuint256 gameId,\\n\\t\\taddress indexed sender,\\n\\t\\taddress indexed recipient,\\n\\t\\tuint256 wagerAmount,\\n\\t\\tuint blockNumber\\n\\t);\\n\\n\\tevent GameAccepted(\\n\\t\\tuint256 gameId,\\n\\t\\taddress indexed sender,\\n\\t\\taddress indexed recipient,\\n\\t\\tuint256 wagerAmount,\\n\\t\\tuint blockNumber\\n\\t);\\n\\n\\tevent GameFinished(\\n\\t\\tuint256 gameId,\\n\\t\\taddress indexed sender,\\n\\t\\taddress indexed recipient\\n\\t);\\n\\n\\tevent GameFinishedByTimelock(\\n\\t\\tuint256 gameId,\\n\\t\\taddress indexed sender,\\n\\t\\taddress indexed recipient\\n\\t);\\n\\n\\t///////////////\\n\\t// PLAYERS //\\n\\t///////////////\\n\\n\\tstruct Player {\\n\\t\\tuint256 player_id;\\n\\t\\tuint256 team_id;\\n\\t\\tuint256 position; // 0 = Empty, 1 = Goalkeeper, 2 = Defense, 3 = Midfield, 4 = Attack\\n\\t\\tuint128 attack;\\n\\t\\tuint128 defense;\\n\\t\\tuint128 speed;\\n\\t\\tuint128 power;\\n\\t\\tuint128 stamina;\\n\\t\\tuint128 technique;\\n\\t\\tuint128 goalkeeping;\\n\\t}\\n\\n\\tmapping(uint256 => Player) public players;\\n\\n\\tfunction addPlayer(\\n\\t\\tuint256 playerId,\\n\\t\\tuint256 teamId,\\n\\t\\tuint256 position,\\n\\t\\tuint128 attack,\\n\\t\\tuint128 defense,\\n\\t\\tuint128 speed,\\n\\t\\tuint128 power,\\n\\t\\tuint128 stamina,\\n\\t\\tuint128 technique,\\n\\t\\tuint128 goalkeeping\\n\\t) public onlyOwner {\\n\\t\\tPlayer memory newPlayer = Player({\\n\\t\\t\\tplayer_id: playerId,\\n\\t\\t\\tteam_id: teamId,\\n\\t\\t\\tposition: position,\\n\\t\\t\\tattack: attack,\\n\\t\\t\\tdefense: defense,\\n\\t\\t\\tspeed: speed,\\n\\t\\t\\tpower: power,\\n\\t\\t\\tstamina: stamina,\\n\\t\\t\\ttechnique: technique,\\n\\t\\t\\tgoalkeeping: goalkeeping\\n\\t\\t});\\n\\n\\t\\tplayers[playerId] = newPlayer;\\n\\t}\\n\\n\\t///////////////\\n\\t// CONSTRUCTOR //\\n\\t///////////////\\n\\n\\tconstructor(IERC20 _footballCoin, uint _timelockBlocks) {\\n\\t\\towner = msg.sender;\\n\\t\\tfootballCoin = _footballCoin;\\n\\t\\ttimelockBlocks = _timelockBlocks;\\n\\t}\\n\\tmodifier onlyOwner() {\\n\\t\\trequire(msg.sender == owner, \\\"Caller is not the owner\\\");\\n\\t\\t_;\\n\\t}\\n\\n\\t///////////////\\n\\t// GAME FUNCTIONS //\\n\\t///////////////\\n\\n\\tfunction proposeGame(\\n\\t\\taddress opponent,\\n\\t\\tuint256 wagerAmount,\\n\\t\\tuint256[] memory formation\\n\\t) public {\\n\\t\\trequire(\\n\\t\\t\\tfootballCoin.allowance(msg.sender, address(this)) >= wagerAmount,\\n\\t\\t\\t\\\"Insufficient allowance for wager\\\"\\n\\t\\t);\\n\\t\\tfor (uint i = 0; i < formation.length; i++) {\\n\\t\\t\\trequire(players[formation[i]].player_id != 0, \\\"Invalid player id\\\");\\n\\t\\t}\\n\\n\\t\\t// Transfer the wager amount from the challenger to the contract\\n\\t\\tfootballCoin.transferFrom(msg.sender, address(this), wagerAmount);\\n\\n\\t\\tuint256 newGameId = ++gameCount;\\n\\t\\tgames[newGameId] = Game({\\n\\t\\t\\tchallenger: msg.sender,\\n\\t\\t\\topponent: opponent,\\n\\t\\t\\twagerAmount: wagerAmount,\\n\\t\\t\\tchallengerFormation: new uint256[](0),\\n\\t\\t\\topponentFormation: new uint256[](0),\\n\\t\\t\\tisFinished: false,\\n\\t\\t\\tresult: GameResult({ goalsHomeTeam: 0, goalsAwayTeam: 0 }),\\n\\t\\t\\tblockNumber: block.number\\n\\t\\t});\\n\\n\\t\\tchallenger_formation[newGameId] = formation;\\n\\n\\t\\t// Emitting events to notify about the new game proposal\\n\\t\\temit GameProposed(\\n\\t\\t\\tnewGameId,\\n\\t\\t\\tmsg.sender,\\n\\t\\t\\topponent,\\n\\t\\t\\twagerAmount,\\n\\t\\t\\tblock.number\\n\\t\\t);\\n\\t}\\n\\n\\tfunction acceptGame(uint256 gameId, uint256[] memory formation) public {\\n\\t\\tGame storage game = games[gameId];\\n\\n\\t\\trequire(\\n\\t\\t\\tmsg.sender == game.opponent,\\n\\t\\t\\t\\\"Only the opponent can accept the game\\\"\\n\\t\\t);\\n\\t\\trequire(\\n\\t\\t\\tfootballCoin.allowance(msg.sender, address(this)) >=\\n\\t\\t\\t\\tgame.wagerAmount,\\n\\t\\t\\t\\\"Insufficient allowance for wager\\\"\\n\\t\\t);\\n\\t\\tfor (uint i = 0; i < formation.length; i++) {\\n\\t\\t\\trequire(players[formation[i]].player_id != 0, \\\"Invalid player id\\\");\\n\\t\\t}\\n\\n\\t\\t// Transfer the wager amount from the opponent to the contract\\n\\t\\tfootballCoin.transferFrom(msg.sender, address(this), game.wagerAmount);\\n\\n\\t\\tgame.opponentFormation = formation;\\n\\t\\tgame.blockNumber = block.number;\\n\\n\\t\\t// Notify about game acceptance\\n\\t\\temit GameAccepted(\\n\\t\\t\\tgameId,\\n\\t\\t\\tmsg.sender,\\n\\t\\t\\tgame.challenger,\\n\\t\\t\\tgame.wagerAmount,\\n\\t\\t\\tblock.number\\n\\t\\t);\\n\\t}\\n\\n\\tfunction revealOutcome(uint256 gameId) public {\\n\\t\\tGame storage game = games[gameId];\\n\\n\\t\\trequire(\\n\\t\\t\\tmsg.sender == game.challenger,\\n\\t\\t\\t\\\"Only the challenger can reveal the outcome\\\"\\n\\t\\t);\\n\\t\\trequire(!game.isFinished, \\\"The game is already finished\\\");\\n\\n\\t\\tgame.challengerFormation = challenger_formation[gameId];\\n\\n\\t\\tGameResult memory result = determineGameResult(game);\\n\\t\\tgameResults[gameId] = result;\\n\\n\\t\\tgame.isFinished = true;\\n\\n\\t\\taddress winner = determineWinner(game, result);\\n\\t\\tpayoutWinners(game, winner);\\n\\n\\t\\temit GameFinished(gameId, msg.sender, game.opponent);\\n\\t}\\n\\n\\tfunction opponentClaimTimelock(uint256 gameId) public {\\n\\t\\tGame storage game = games[gameId];\\n\\n\\t\\trequire(\\n\\t\\t\\tmsg.sender == game.opponent,\\n\\t\\t\\t\\\"Only the opponent can claim the timelock\\\"\\n\\t\\t);\\n\\t\\trequire(\\n\\t\\t\\tblock.number > game.blockNumber + timelockBlocks,\\n\\t\\t\\t\\\"Opponent can claim timelock only after timelockBlocks have passed\\\"\\n\\t\\t);\\n\\n\\t\\tgame.isFinished = true;\\n\\t\\tpayoutWinners(game, game.opponent);\\n\\n\\t\\temit GameFinishedByTimelock(gameId, msg.sender, game.challenger);\\n\\t}\\n\\n\\t///////////////\\n\\t// HELPER FUNCTIONS //\\n\\t///////////////\\n\\n\\tfunction determineGameResult(\\n\\t\\tGame storage game\\n\\t) private view returns (GameResult memory) {\\n\\t\\tGameResult memory result = GameResult({\\n\\t\\t\\tgoalsHomeTeam: 0,\\n\\t\\t\\tgoalsAwayTeam: 0\\n\\t\\t});\\n\\n\\t\\t// Player memory homeGoalkeeper = players[game.challengerFormation[1]];\\n\\t\\t// Player memory awayGoalkeeper = players[game.opponentFormation[1]];\\n\\t\\tbytes32 prevRandao = blockhash(block.number - 1);\\n\\t\\tuint256[] memory randomValues = extractRandomValues(10, prevRandao);\\n\\t\\tfor (uint i = 1; i < game.challengerFormation.length; i++) {\\n\\t\\t\\tPlayer memory homePlayer = players[game.challengerFormation[i]];\\n\\t\\t\\tPlayer memory awayPlayer = players[\\n\\t\\t\\t\\tgame.opponentFormation[game.challengerFormation.length - i]\\n\\t\\t\\t];\\n\\t\\t\\tuint256 totalspeed = homePlayer.speed + awayPlayer.speed;\\n\\t\\t\\tuint256 randomSpeed = uint256(prevRandao) % totalspeed;\\n\\t\\t\\tif (homePlayer.speed > randomSpeed) {\\n\\t\\t\\t\\t// Home player attacks\\n\\t\\t\\t\\tif (homePlayer.attack > randomValues[i - 1]) {\\n\\t\\t\\t\\t\\tresult.goalsHomeTeam++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (awayPlayer.attack > randomValues[i - 1]) {\\n\\t\\t\\t\\t\\tresult.goalsAwayTeam++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\treturn result;\\n\\t}\\n\\n\\tfunction extractRandomValues(\\n\\t\\tuint numberOfValues,\\n\\t\\tbytes32 prevRandao\\n\\t) public pure returns (uint[] memory) {\\n\\t\\trequire(numberOfValues > 0, \\\"Number of values must be greater than 0\\\");\\n\\t\\tuint[] memory randomValues = new uint[](numberOfValues);\\n\\t\\tuint256 randValue = uint256(prevRandao);\\n\\n\\t\\tfor (uint i = 0; i < numberOfValues; i++) {\\n\\t\\t\\trandomValues[i] = randValue % 100;\\n\\t\\t\\trandValue = randValue / 256; // Shift right by 2 hex digits\\n\\t\\t}\\n\\n\\t\\treturn randomValues;\\n\\t}\\n\\n\\tfunction determineWinner(\\n\\t\\tGame storage game,\\n\\t\\tGameResult memory result\\n\\t) private view returns (address) {\\n\\t\\tif (result.goalsHomeTeam > result.goalsAwayTeam) {\\n\\t\\t\\treturn game.challenger;\\n\\t\\t} else if (result.goalsHomeTeam < result.goalsAwayTeam) {\\n\\t\\t\\treturn game.opponent;\\n\\t\\t}\\n\\t\\treturn address(0); // It's a draw\\n\\t}\\n\\n\\tfunction payoutWinners(Game storage game, address winner) private {\\n\\t\\tif (winner == address(0)) {\\n\\t\\t\\trequire(\\n\\t\\t\\t\\tfootballCoin.transfer(game.challenger, game.wagerAmount),\\n\\t\\t\\t\\t\\\"Transfer to challenger failed\\\"\\n\\t\\t\\t);\\n\\t\\t\\trequire(\\n\\t\\t\\t\\tfootballCoin.transfer(game.opponent, game.wagerAmount),\\n\\t\\t\\t\\t\\\"Transfer to opponent failed\\\"\\n\\t\\t\\t);\\n\\t\\t} else {\\n\\t\\t\\tuint256 totalPot = game.wagerAmount * 2;\\n\\t\\t\\trequire(\\n\\t\\t\\t\\tfootballCoin.transfer(winner, totalPot),\\n\\t\\t\\t\\t\\\"Transfer to winner failed\\\"\\n\\t\\t\\t);\\n\\t\\t}\\n\\t}\\n}\\n\",\"keccak256\":\"0x9abf23273d65c0881c0221f47cc9ed4c1012b4e349a8df9feac2ac5f90d2efce\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051611b15380380611b1583398101604081905261002f91610066565b60008054336001600160a01b031991821617909155600180549091166001600160a01b0393909316929092179091556002556100a0565b6000806040838503121561007957600080fd5b82516001600160a01b038116811461009057600080fd5b6020939093015192949293505050565b611a66806100af6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806394b1e59511610097578063ed2df26d11610066578063ed2df26d1461025d578063f71d96cb146102b6578063fda0f9a214610386578063fdba1b7c1461038f57600080fd5b806394b1e5951461021c578063cd86f8101461022f578063cfb9479814610242578063e87c0ee61461025557600080fd5b806352bab1c9116100d357806352bab1c9146101ab57806359c892a9146101cb57806364407bad146101de5780638da5cb5b1461020957600080fd5b8063117a5b90146100fa5780634d1975b41461017f578063506d7e2d14610196575b600080fd5b610164610108366004611604565b60046020908152600091825260409182902080546001820154600283015460058401548651808801909752600685015487526007850154958701959095526008909301546001600160a01b0392831695919092169360ff169186565b6040516101769695949392919061161d565b60405180910390f35b61018860065481565b604051908152602001610176565b6101a96101a4366004611688565b6103cb565b005b6101be6101b936600461172d565b61051b565b604051610176919061174f565b6101a96101d9366004611844565b610624565b6001546101f1906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b6000546101f1906001600160a01b031681565b6101a961022a366004611604565b6108ed565b6101a961023d36600461188b565b610a68565b6101a9610250366004611604565b610e26565b600654610188565b6102a961026b366004611604565b604080518082019091526000808252602082015250600090815260056020908152604091829020825180840190935280548352600101549082015290565b60405161017691906118f0565b6103296102c4366004611604565b60076020526000908152604090208054600182015460028301546003840154600485015460058601546006909601549495939492936001600160801b0380841694600160801b948590048216948483169481900483169380841693919004811691168a565b604080519a8b5260208b0199909952978901969096526001600160801b039485166060890152928416608088015290831660a0870152821660c0860152811660e08501529081166101008401521661012082015261014001610176565b61018860025481565b6103b661039d366004611604565b6005602052600090815260409020805460019091015482565b60408051928352602083019190915201610176565b6000546001600160a01b0316331461042a5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064015b60405180910390fd5b60408051610140810182528b815260208082019b8c528183019a8b526001600160801b03998a1660608301908152988a1660808301908152978a1660a08301908152968a1660c08301908152958a1660e08301908152948a166101008301908152938a16610120830190815260009d8e52600790915291909b209a518b55985160018b0155965160028a015593519251928516600160801b938616840217600389015590519051908416908416820217600487015590519251928216928216029190911760058401559051600690920180546fffffffffffffffffffffffffffffffff191692909116919091179055565b60606000831161057d5760405162461bcd60e51b815260206004820152602760248201527f4e756d626572206f662076616c756573206d75737420626520677265617465726044820152660207468616e20360cc1b6064820152608401610421565b60008367ffffffffffffffff81111561059857610598611793565b6040519080825280602002602001820160405280156105c1578160200160208202803683370190505b5090508260005b85811015610618576105db60648361191d565b8382815181106105ed576105ed611931565b60209081029190910101526106046101008361195d565b91508061061081611971565b9150506105c8565b50909150505b92915050565b600082815260046020526040902060018101546001600160a01b0316331461069c5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c7920746865206f70706f6e656e742063616e20616363657074207468656044820152642067616d6560d81b6064820152608401610421565b6002810154600154604051636eb1769f60e11b81523360048201523060248201526001600160a01b039091169063dd62ed3e90604401602060405180830381865afa1580156106ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610713919061198a565b10156107615760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b82518110156107f2576007600084838151811061078357610783611931565b60200260200101518152602001908152602001600020600001546000036107e05760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b806107ea81611971565b915050610764565b5060015460028201546040516323b872dd60e01b815233600482015230602482015260448101919091526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610850573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087491906119a3565b50815161088a9060048301906020850190611564565b504360088201819055815460028301546040805187815260208101929092528101929092526001600160a01b03169033907f3f9bd1ba680334360f5cfe7c55feb3bb67931ebd35c2020b389a5a52a9cc1eb49060600160405180910390a3505050565b600081815260046020526040902060018101546001600160a01b031633146109685760405162461bcd60e51b815260206004820152602860248201527f4f6e6c7920746865206f70706f6e656e742063616e20636c61696d207468652060448201526774696d656c6f636b60c01b6064820152608401610421565b600254816008015461097a91906119cc565b43116109f85760405162461bcd60e51b815260206004820152604160248201527f4f70706f6e656e742063616e20636c61696d2074696d656c6f636b206f6e6c7960448201527f2061667465722074696d656c6f636b426c6f636b7320686176652070617373656064820152601960fa1b608482015260a401610421565b60058101805460ff19166001908117909155810154610a219082906001600160a01b0316610fa9565b80546040518381526001600160a01b039091169033907fb6f60e952021d7bcf89b0cc9d3fac667423e6df8dba9bfeedca45c5b8c166adf9060200160405180910390a35050565b600154604051636eb1769f60e11b815233600482015230602482015283916001600160a01b03169063dd62ed3e90604401602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061198a565b1015610b285760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b8151811015610bb95760076000838381518110610b4a57610b4a611931565b6020026020010151815260200190815260200160002060000154600003610ba75760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b80610bb181611971565b915050610b2b565b506001546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3591906119a3565b506000600660008154610c4790611971565b918290555060408051610100810182523381526001600160a01b0387166020820152908101859052909150606081016000604051908082528060200260200182016040528015610ca1578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610cd2578160200160208202803683370190505b5081526000602080830182905260408051808201825283815280830184905281850152436060948501528583526004825291829020845181546001600160a01b039182166001600160a01b0319918216178355868401516001840180549190931691161790559184015160028301559183015180519192610d5b92600385019290910190611564565b5060808201518051610d77916004840191602090910190611564565b5060a082015160058201805460ff191691151591909117905560c082015180516006830155602090810151600783015560e090920151600890910155600082815260038252604090208351610dce92850190611564565b50604080518281526020810185905243918101919091526001600160a01b0385169033907f02c4c4ed29b388428cf1564d10b179c4153a007fb74269c8cc4681465146f50a906060015b60405180910390a350505050565b600081815260046020526040902080546001600160a01b03163314610ea05760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c7920746865206368616c6c656e6765722063616e2072657665616c20746044820152696865206f7574636f6d6560b01b6064820152608401610421565b600581015460ff1615610ef55760405162461bcd60e51b815260206004820152601c60248201527f5468652067616d6520697320616c72656164792066696e6973686564000000006044820152606401610421565b60008281526003602081905260409091208054610f1592840191906115af565b506000610f218261122f565b600084815260056020818152604083208451815590840151600191820155908501805460ff19169091179055909150610f5a8383611517565b9050610f668382610fa9565b60018301546040518581526001600160a01b039091169033907f242f4c122901edd03165283a5957c7f0445c5227fdaebe5fc500f2c62c61ae0990602001610e18565b6001600160a01b038116611152576001548254600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af1158015611011573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103591906119a3565b6110815760405162461bcd60e51b815260206004820152601d60248201527f5472616e7366657220746f206368616c6c656e676572206661696c65640000006044820152606401610421565b6001805490830154600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af11580156110de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110291906119a3565b61114e5760405162461bcd60e51b815260206004820152601b60248201527f5472616e7366657220746f206f70706f6e656e74206661696c656400000000006044820152606401610421565b5050565b60008260020154600261116591906119df565b60015460405163a9059cbb60e01b81526001600160a01b0385811660048301526024820184905292935091169063a9059cbb906044016020604051808303816000875af11580156111ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de91906119a3565b61122a5760405162461bcd60e51b815260206004820152601960248201527f5472616e7366657220746f2077696e6e6572206661696c6564000000000000006044820152606401610421565b505050565b6040805180820190915260008082526020820152604080518082019091526000808252602082018190526112646001436119f6565b4090506000611274600a8361051b565b905060015b600386015481101561150d576000600760008860030184815481106112a0576112a0611931565b600091825260208083209091015483528281019390935260409182018120825161014081018452815481526001820154948101949094526002810154928401929092526003808301546001600160801b038082166060870152600160801b918290048116608087015260048086015480831660a0890152839004821660c0880152600586015480831660e08901529290920481166101008701526006909401549093166101208501528a0154929350916007918391908b01906113649087906119f6565b8154811061137457611374611931565b6000918252602080832090910154835282810193909352604091820181208251610140810184528154815260018201549481019490945260028101549284019290925260038201546001600160801b038082166060860152600160801b9182900481166080860152600484015480821660a080880182905291849004831660c0880152600586015480841660e089015293909304821661010087015260069094015416610120850152918501519293509161142f9190611a09565b6001600160801b031690506000611446828861191d565b9050808460a001516001600160801b031611156114aa57856114696001876119f6565b8151811061147957611479611931565b602002602001015184606001516001600160801b031611156114a5578751886114a182611971565b9052505b6114f6565b856114b66001876119f6565b815181106114c6576114c6611931565b602002602001015183606001516001600160801b031611156114f657602088018051906114f282611971565b9052505b50505050808061150590611971565b915050611279565b5091949350505050565b600081602001518260000151111561153a575081546001600160a01b031661061e565b60208201518251101561155b575060018201546001600160a01b031661061e565b50600092915050565b82805482825590600052602060002090810192821561159f579160200282015b8281111561159f578251825591602001919060010190611584565b506115ab9291506115ef565b5090565b82805482825590600052602060002090810192821561159f5760005260206000209182015b8281111561159f5782548255916001019190600101906115d4565b5b808211156115ab57600081556001016115f0565b60006020828403121561161657600080fd5b5035919050565b6001600160a01b0387811682528616602082015260408101859052831515606082015260e0810161165b608083018580518252602090810151910152565b8260c0830152979650505050505050565b80356001600160801b038116811461168357600080fd5b919050565b6000806000806000806000806000806101408b8d0312156116a857600080fd5b8a35995060208b0135985060408b013597506116c660608c0161166c565b96506116d460808c0161166c565b95506116e260a08c0161166c565b94506116f060c08c0161166c565b93506116fe60e08c0161166c565b925061170d6101008c0161166c565b915061171c6101208c0161166c565b90509295989b9194979a5092959850565b6000806040838503121561174057600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156117875783518352928401929184019160010161176b565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126117ba57600080fd5b8135602067ffffffffffffffff808311156117d7576117d7611793565b8260051b604051601f19603f830116810181811084821117156117fc576117fc611793565b60405293845285810183019383810192508785111561181a57600080fd5b83870191505b8482101561183957813583529183019190830190611820565b979650505050505050565b6000806040838503121561185757600080fd5b82359150602083013567ffffffffffffffff81111561187557600080fd5b611881858286016117a9565b9150509250929050565b6000806000606084860312156118a057600080fd5b83356001600160a01b03811681146118b757600080fd5b925060208401359150604084013567ffffffffffffffff8111156118da57600080fd5b6118e6868287016117a9565b9150509250925092565b81518152602080830151908201526040810161061e565b634e487b7160e01b600052601260045260246000fd5b60008261192c5761192c611907565b500690565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008261196c5761196c611907565b500490565b60006001820161198357611983611947565b5060010190565b60006020828403121561199c57600080fd5b5051919050565b6000602082840312156119b557600080fd5b815180151581146119c557600080fd5b9392505050565b8082018082111561061e5761061e611947565b808202811582820484141761061e5761061e611947565b8181038181111561061e5761061e611947565b6001600160801b03818116838216019080821115611a2957611a29611947565b509291505056fea26469706673582212200aed7f057f5619a0f91da70f61fe49af27e71ce596851cca19d1732fbc45318264736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806394b1e59511610097578063ed2df26d11610066578063ed2df26d1461025d578063f71d96cb146102b6578063fda0f9a214610386578063fdba1b7c1461038f57600080fd5b806394b1e5951461021c578063cd86f8101461022f578063cfb9479814610242578063e87c0ee61461025557600080fd5b806352bab1c9116100d357806352bab1c9146101ab57806359c892a9146101cb57806364407bad146101de5780638da5cb5b1461020957600080fd5b8063117a5b90146100fa5780634d1975b41461017f578063506d7e2d14610196575b600080fd5b610164610108366004611604565b60046020908152600091825260409182902080546001820154600283015460058401548651808801909752600685015487526007850154958701959095526008909301546001600160a01b0392831695919092169360ff169186565b6040516101769695949392919061161d565b60405180910390f35b61018860065481565b604051908152602001610176565b6101a96101a4366004611688565b6103cb565b005b6101be6101b936600461172d565b61051b565b604051610176919061174f565b6101a96101d9366004611844565b610624565b6001546101f1906001600160a01b031681565b6040516001600160a01b039091168152602001610176565b6000546101f1906001600160a01b031681565b6101a961022a366004611604565b6108ed565b6101a961023d36600461188b565b610a68565b6101a9610250366004611604565b610e26565b600654610188565b6102a961026b366004611604565b604080518082019091526000808252602082015250600090815260056020908152604091829020825180840190935280548352600101549082015290565b60405161017691906118f0565b6103296102c4366004611604565b60076020526000908152604090208054600182015460028301546003840154600485015460058601546006909601549495939492936001600160801b0380841694600160801b948590048216948483169481900483169380841693919004811691168a565b604080519a8b5260208b0199909952978901969096526001600160801b039485166060890152928416608088015290831660a0870152821660c0860152811660e08501529081166101008401521661012082015261014001610176565b61018860025481565b6103b661039d366004611604565b6005602052600090815260409020805460019091015482565b60408051928352602083019190915201610176565b6000546001600160a01b0316331461042a5760405162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064015b60405180910390fd5b60408051610140810182528b815260208082019b8c528183019a8b526001600160801b03998a1660608301908152988a1660808301908152978a1660a08301908152968a1660c08301908152958a1660e08301908152948a166101008301908152938a16610120830190815260009d8e52600790915291909b209a518b55985160018b0155965160028a015593519251928516600160801b938616840217600389015590519051908416908416820217600487015590519251928216928216029190911760058401559051600690920180546fffffffffffffffffffffffffffffffff191692909116919091179055565b60606000831161057d5760405162461bcd60e51b815260206004820152602760248201527f4e756d626572206f662076616c756573206d75737420626520677265617465726044820152660207468616e20360cc1b6064820152608401610421565b60008367ffffffffffffffff81111561059857610598611793565b6040519080825280602002602001820160405280156105c1578160200160208202803683370190505b5090508260005b85811015610618576105db60648361191d565b8382815181106105ed576105ed611931565b60209081029190910101526106046101008361195d565b91508061061081611971565b9150506105c8565b50909150505b92915050565b600082815260046020526040902060018101546001600160a01b0316331461069c5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c7920746865206f70706f6e656e742063616e20616363657074207468656044820152642067616d6560d81b6064820152608401610421565b6002810154600154604051636eb1769f60e11b81523360048201523060248201526001600160a01b039091169063dd62ed3e90604401602060405180830381865afa1580156106ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610713919061198a565b10156107615760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b82518110156107f2576007600084838151811061078357610783611931565b60200260200101518152602001908152602001600020600001546000036107e05760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b806107ea81611971565b915050610764565b5060015460028201546040516323b872dd60e01b815233600482015230602482015260448101919091526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610850573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087491906119a3565b50815161088a9060048301906020850190611564565b504360088201819055815460028301546040805187815260208101929092528101929092526001600160a01b03169033907f3f9bd1ba680334360f5cfe7c55feb3bb67931ebd35c2020b389a5a52a9cc1eb49060600160405180910390a3505050565b600081815260046020526040902060018101546001600160a01b031633146109685760405162461bcd60e51b815260206004820152602860248201527f4f6e6c7920746865206f70706f6e656e742063616e20636c61696d207468652060448201526774696d656c6f636b60c01b6064820152608401610421565b600254816008015461097a91906119cc565b43116109f85760405162461bcd60e51b815260206004820152604160248201527f4f70706f6e656e742063616e20636c61696d2074696d656c6f636b206f6e6c7960448201527f2061667465722074696d656c6f636b426c6f636b7320686176652070617373656064820152601960fa1b608482015260a401610421565b60058101805460ff19166001908117909155810154610a219082906001600160a01b0316610fa9565b80546040518381526001600160a01b039091169033907fb6f60e952021d7bcf89b0cc9d3fac667423e6df8dba9bfeedca45c5b8c166adf9060200160405180910390a35050565b600154604051636eb1769f60e11b815233600482015230602482015283916001600160a01b03169063dd62ed3e90604401602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061198a565b1015610b285760405162461bcd60e51b815260206004820181905260248201527f496e73756666696369656e7420616c6c6f77616e636520666f722077616765726044820152606401610421565b60005b8151811015610bb95760076000838381518110610b4a57610b4a611931565b6020026020010151815260200190815260200160002060000154600003610ba75760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c1b185e595c881a59607a1b6044820152606401610421565b80610bb181611971565b915050610b2b565b506001546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015610c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3591906119a3565b506000600660008154610c4790611971565b918290555060408051610100810182523381526001600160a01b0387166020820152908101859052909150606081016000604051908082528060200260200182016040528015610ca1578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610cd2578160200160208202803683370190505b5081526000602080830182905260408051808201825283815280830184905281850152436060948501528583526004825291829020845181546001600160a01b039182166001600160a01b0319918216178355868401516001840180549190931691161790559184015160028301559183015180519192610d5b92600385019290910190611564565b5060808201518051610d77916004840191602090910190611564565b5060a082015160058201805460ff191691151591909117905560c082015180516006830155602090810151600783015560e090920151600890910155600082815260038252604090208351610dce92850190611564565b50604080518281526020810185905243918101919091526001600160a01b0385169033907f02c4c4ed29b388428cf1564d10b179c4153a007fb74269c8cc4681465146f50a906060015b60405180910390a350505050565b600081815260046020526040902080546001600160a01b03163314610ea05760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c7920746865206368616c6c656e6765722063616e2072657665616c20746044820152696865206f7574636f6d6560b01b6064820152608401610421565b600581015460ff1615610ef55760405162461bcd60e51b815260206004820152601c60248201527f5468652067616d6520697320616c72656164792066696e6973686564000000006044820152606401610421565b60008281526003602081905260409091208054610f1592840191906115af565b506000610f218261122f565b600084815260056020818152604083208451815590840151600191820155908501805460ff19169091179055909150610f5a8383611517565b9050610f668382610fa9565b60018301546040518581526001600160a01b039091169033907f242f4c122901edd03165283a5957c7f0445c5227fdaebe5fc500f2c62c61ae0990602001610e18565b6001600160a01b038116611152576001548254600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af1158015611011573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103591906119a3565b6110815760405162461bcd60e51b815260206004820152601d60248201527f5472616e7366657220746f206368616c6c656e676572206661696c65640000006044820152606401610421565b6001805490830154600284015460405163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb906044016020604051808303816000875af11580156110de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110291906119a3565b61114e5760405162461bcd60e51b815260206004820152601b60248201527f5472616e7366657220746f206f70706f6e656e74206661696c656400000000006044820152606401610421565b5050565b60008260020154600261116591906119df565b60015460405163a9059cbb60e01b81526001600160a01b0385811660048301526024820184905292935091169063a9059cbb906044016020604051808303816000875af11580156111ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111de91906119a3565b61122a5760405162461bcd60e51b815260206004820152601960248201527f5472616e7366657220746f2077696e6e6572206661696c6564000000000000006044820152606401610421565b505050565b6040805180820190915260008082526020820152604080518082019091526000808252602082018190526112646001436119f6565b4090506000611274600a8361051b565b905060015b600386015481101561150d576000600760008860030184815481106112a0576112a0611931565b600091825260208083209091015483528281019390935260409182018120825161014081018452815481526001820154948101949094526002810154928401929092526003808301546001600160801b038082166060870152600160801b918290048116608087015260048086015480831660a0890152839004821660c0880152600586015480831660e08901529290920481166101008701526006909401549093166101208501528a0154929350916007918391908b01906113649087906119f6565b8154811061137457611374611931565b6000918252602080832090910154835282810193909352604091820181208251610140810184528154815260018201549481019490945260028101549284019290925260038201546001600160801b038082166060860152600160801b9182900481166080860152600484015480821660a080880182905291849004831660c0880152600586015480841660e089015293909304821661010087015260069094015416610120850152918501519293509161142f9190611a09565b6001600160801b031690506000611446828861191d565b9050808460a001516001600160801b031611156114aa57856114696001876119f6565b8151811061147957611479611931565b602002602001015184606001516001600160801b031611156114a5578751886114a182611971565b9052505b6114f6565b856114b66001876119f6565b815181106114c6576114c6611931565b602002602001015183606001516001600160801b031611156114f657602088018051906114f282611971565b9052505b50505050808061150590611971565b915050611279565b5091949350505050565b600081602001518260000151111561153a575081546001600160a01b031661061e565b60208201518251101561155b575060018201546001600160a01b031661061e565b50600092915050565b82805482825590600052602060002090810192821561159f579160200282015b8281111561159f578251825591602001919060010190611584565b506115ab9291506115ef565b5090565b82805482825590600052602060002090810192821561159f5760005260206000209182015b8281111561159f5782548255916001019190600101906115d4565b5b808211156115ab57600081556001016115f0565b60006020828403121561161657600080fd5b5035919050565b6001600160a01b0387811682528616602082015260408101859052831515606082015260e0810161165b608083018580518252602090810151910152565b8260c0830152979650505050505050565b80356001600160801b038116811461168357600080fd5b919050565b6000806000806000806000806000806101408b8d0312156116a857600080fd5b8a35995060208b0135985060408b013597506116c660608c0161166c565b96506116d460808c0161166c565b95506116e260a08c0161166c565b94506116f060c08c0161166c565b93506116fe60e08c0161166c565b925061170d6101008c0161166c565b915061171c6101208c0161166c565b90509295989b9194979a5092959850565b6000806040838503121561174057600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156117875783518352928401929184019160010161176b565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126117ba57600080fd5b8135602067ffffffffffffffff808311156117d7576117d7611793565b8260051b604051601f19603f830116810181811084821117156117fc576117fc611793565b60405293845285810183019383810192508785111561181a57600080fd5b83870191505b8482101561183957813583529183019190830190611820565b979650505050505050565b6000806040838503121561185757600080fd5b82359150602083013567ffffffffffffffff81111561187557600080fd5b611881858286016117a9565b9150509250929050565b6000806000606084860312156118a057600080fd5b83356001600160a01b03811681146118b757600080fd5b925060208401359150604084013567ffffffffffffffff8111156118da57600080fd5b6118e6868287016117a9565b9150509250925092565b81518152602080830151908201526040810161061e565b634e487b7160e01b600052601260045260246000fd5b60008261192c5761192c611907565b500690565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008261196c5761196c611907565b500490565b60006001820161198357611983611947565b5060010190565b60006020828403121561199c57600080fd5b5051919050565b6000602082840312156119b557600080fd5b815180151581146119c557600080fd5b9392505050565b8082018082111561061e5761061e611947565b808202811582820484141761061e5761061e611947565b8181038181111561061e5761061e611947565b6001600160801b03818116838216019080821115611a2957611a29611947565b509291505056fea26469706673582212200aed7f057f5619a0f91da70f61fe49af27e71ce596851cca19d1732fbc45318264736f6c63430008110033", "devdoc": { "kind": "dev", "methods": {}, @@ -595,12 +625,12 @@ "type": "t_uint256" }, { - "astId": 206, + "astId": 216, "contract": "contracts/FootballGame.sol:FootballGame", "label": "players", "offset": 0, "slot": "7", - "type": "t_mapping(t_uint256,t_struct(Player)201_storage)" + "type": "t_mapping(t_uint256,t_struct(Player)211_storage)" } ], "types": { @@ -646,12 +676,12 @@ "numberOfBytes": "32", "value": "t_struct(GameResult)112_storage" }, - "t_mapping(t_uint256,t_struct(Player)201_storage)": { + "t_mapping(t_uint256,t_struct(Player)211_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct FootballGame.Player)", "numberOfBytes": "32", - "value": "t_struct(Player)201_storage" + "value": "t_struct(Player)211_storage" }, "t_struct(Game)107_storage": { "encoding": "inplace", @@ -747,12 +777,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Player)201_storage": { + "t_struct(Player)211_storage": { "encoding": "inplace", "label": "struct FootballGame.Player", "members": [ { - "astId": 182, + "astId": 192, "contract": "contracts/FootballGame.sol:FootballGame", "label": "player_id", "offset": 0, @@ -760,7 +790,7 @@ "type": "t_uint256" }, { - "astId": 184, + "astId": 194, "contract": "contracts/FootballGame.sol:FootballGame", "label": "team_id", "offset": 0, @@ -768,7 +798,7 @@ "type": "t_uint256" }, { - "astId": 186, + "astId": 196, "contract": "contracts/FootballGame.sol:FootballGame", "label": "position", "offset": 0, @@ -776,7 +806,7 @@ "type": "t_uint256" }, { - "astId": 188, + "astId": 198, "contract": "contracts/FootballGame.sol:FootballGame", "label": "attack", "offset": 0, @@ -784,7 +814,7 @@ "type": "t_uint128" }, { - "astId": 190, + "astId": 200, "contract": "contracts/FootballGame.sol:FootballGame", "label": "defense", "offset": 16, @@ -792,7 +822,7 @@ "type": "t_uint128" }, { - "astId": 192, + "astId": 202, "contract": "contracts/FootballGame.sol:FootballGame", "label": "speed", "offset": 0, @@ -800,7 +830,7 @@ "type": "t_uint128" }, { - "astId": 194, + "astId": 204, "contract": "contracts/FootballGame.sol:FootballGame", "label": "power", "offset": 16, @@ -808,7 +838,7 @@ "type": "t_uint128" }, { - "astId": 196, + "astId": 206, "contract": "contracts/FootballGame.sol:FootballGame", "label": "stamina", "offset": 0, @@ -816,7 +846,7 @@ "type": "t_uint128" }, { - "astId": 198, + "astId": 208, "contract": "contracts/FootballGame.sol:FootballGame", "label": "technique", "offset": 16, @@ -824,7 +854,7 @@ "type": "t_uint128" }, { - "astId": 200, + "astId": 210, "contract": "contracts/FootballGame.sol:FootballGame", "label": "goalkeeping", "offset": 0, diff --git a/packages/hardhat/deployments/ten/solcInputs/28b373b67d70fb99a146639d53e9ea17.json b/packages/hardhat/deployments/ten/solcInputs/28b373b67d70fb99a146639d53e9ea17.json new file mode 100644 index 0000000..0aa6051 --- /dev/null +++ b/packages/hardhat/deployments/ten/solcInputs/28b373b67d70fb99a146639d53e9ea17.json @@ -0,0 +1,38 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "contracts/FootballGame.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract FootballGame {\n\taddress public owner;\n\tIERC20 public footballCoin;\n\tuint public timelockBlocks;\n\n\tstruct Game {\n\t\taddress challenger;\n\t\taddress opponent;\n\t\tuint256 wagerAmount;\n\t\tuint256[] challengerFormation;\n\t\tuint256[] opponentFormation;\n\t\tbool isFinished;\n\t\tGameResult result;\n\t\tuint blockNumber;\n\t}\n\n\tstruct GameResult {\n\t\tuint goalsHomeTeam;\n\t\tuint goalsAwayTeam;\n\t}\n\n\t///////////////\n\t// MAPPINGS //\n\t///////////////\n\n\tmapping(uint256 => uint256[]) private challenger_formation;\n\tmapping(uint256 => Game) public games;\n\tmapping(uint256 => GameResult) public gameResults;\n\tuint256 public gameCount;\n\n\tfunction getGameResult(\n\t\tuint256 gameId\n\t) public view returns (GameResult memory) {\n\t\treturn gameResults[gameId];\n\t}\n\n\tfunction getGameCount() public view returns (uint256) {\n\t\treturn gameCount;\n\t}\n\n\t///////////////\n\t// EVENTS //\n\t///////////////\n\n\tevent GameProposed(\n\t\tuint256 gameId,\n\t\taddress indexed sender,\n\t\taddress indexed recipient,\n\t\tuint256 wagerAmount,\n\t\tuint blockNumber\n\t);\n\n\tevent GameAccepted(\n\t\tuint256 gameId,\n\t\taddress indexed sender,\n\t\taddress indexed recipient,\n\t\tuint256 wagerAmount,\n\t\tuint blockNumber\n\t);\n\n\tevent GameFinished(\n\t\tuint256 gameId,\n\t\taddress indexed sender,\n\t\taddress indexed recipient\n\t);\n\n\tevent GameFinishedByTimelock(\n\t\tuint256 gameId,\n\t\taddress indexed sender,\n\t\taddress indexed recipient\n\t);\n\n\t///////////////\n\t// PLAYERS //\n\t///////////////\n\n\tstruct Player {\n\t\tuint256 player_id;\n\t\tuint256 team_id;\n\t\tuint256 position; // 0 = Empty, 1 = Goalkeeper, 2 = Defense, 3 = Midfield, 4 = Attack\n\t\tuint128 attack;\n\t\tuint128 defense;\n\t\tuint128 speed;\n\t\tuint128 power;\n\t\tuint128 stamina;\n\t\tuint128 technique;\n\t\tuint128 goalkeeping;\n\t}\n\n\tmapping(uint256 => Player) public players;\n\n\tfunction addPlayer(\n\t\tuint256 playerId,\n\t\tuint256 teamId,\n\t\tuint256 position,\n\t\tuint128 attack,\n\t\tuint128 defense,\n\t\tuint128 speed,\n\t\tuint128 power,\n\t\tuint128 stamina,\n\t\tuint128 technique,\n\t\tuint128 goalkeeping\n\t) public onlyOwner {\n\t\tPlayer memory newPlayer = Player({\n\t\t\tplayer_id: playerId,\n\t\t\tteam_id: teamId,\n\t\t\tposition: position,\n\t\t\tattack: attack,\n\t\t\tdefense: defense,\n\t\t\tspeed: speed,\n\t\t\tpower: power,\n\t\t\tstamina: stamina,\n\t\t\ttechnique: technique,\n\t\t\tgoalkeeping: goalkeeping\n\t\t});\n\n\t\tplayers[playerId] = newPlayer;\n\t}\n\n\t///////////////\n\t// CONSTRUCTOR //\n\t///////////////\n\n\tconstructor(IERC20 _footballCoin, uint _timelockBlocks) {\n\t\towner = msg.sender;\n\t\tfootballCoin = _footballCoin;\n\t\ttimelockBlocks = _timelockBlocks;\n\t}\n\tmodifier onlyOwner() {\n\t\trequire(msg.sender == owner, \"Caller is not the owner\");\n\t\t_;\n\t}\n\n\t///////////////\n\t// GAME FUNCTIONS //\n\t///////////////\n\n\tfunction proposeGame(\n\t\taddress opponent,\n\t\tuint256 wagerAmount,\n\t\tuint256[] memory formation\n\t) public {\n\t\trequire(\n\t\t\tfootballCoin.allowance(msg.sender, address(this)) >= wagerAmount,\n\t\t\t\"Insufficient allowance for wager\"\n\t\t);\n\t\tfor (uint i = 0; i < formation.length; i++) {\n\t\t\trequire(players[formation[i]].player_id != 0, \"Invalid player id\");\n\t\t}\n\n\t\t// Transfer the wager amount from the challenger to the contract\n\t\tfootballCoin.transferFrom(msg.sender, address(this), wagerAmount);\n\n\t\tuint256 newGameId = ++gameCount;\n\t\tgames[newGameId] = Game({\n\t\t\tchallenger: msg.sender,\n\t\t\topponent: opponent,\n\t\t\twagerAmount: wagerAmount,\n\t\t\tchallengerFormation: new uint256[](0),\n\t\t\topponentFormation: new uint256[](0),\n\t\t\tisFinished: false,\n\t\t\tresult: GameResult({ goalsHomeTeam: 0, goalsAwayTeam: 0 }),\n\t\t\tblockNumber: block.number\n\t\t});\n\n\t\tchallenger_formation[newGameId] = formation;\n\n\t\t// Emitting events to notify about the new game proposal\n\t\temit GameProposed(\n\t\t\tnewGameId,\n\t\t\tmsg.sender,\n\t\t\topponent,\n\t\t\twagerAmount,\n\t\t\tblock.number\n\t\t);\n\t}\n\n\tfunction acceptGame(uint256 gameId, uint256[] memory formation) public {\n\t\tGame storage game = games[gameId];\n\n\t\trequire(\n\t\t\tmsg.sender == game.opponent,\n\t\t\t\"Only the opponent can accept the game\"\n\t\t);\n\t\trequire(\n\t\t\tfootballCoin.allowance(msg.sender, address(this)) >=\n\t\t\t\tgame.wagerAmount,\n\t\t\t\"Insufficient allowance for wager\"\n\t\t);\n\t\tfor (uint i = 0; i < formation.length; i++) {\n\t\t\trequire(players[formation[i]].player_id != 0, \"Invalid player id\");\n\t\t}\n\n\t\t// Transfer the wager amount from the opponent to the contract\n\t\tfootballCoin.transferFrom(msg.sender, address(this), game.wagerAmount);\n\n\t\tgame.opponentFormation = formation;\n\t\tgame.blockNumber = block.number;\n\n\t\t// Notify about game acceptance\n\t\temit GameAccepted(\n\t\t\tgameId,\n\t\t\tmsg.sender,\n\t\t\tgame.challenger,\n\t\t\tgame.wagerAmount,\n\t\t\tblock.number\n\t\t);\n\t}\n\n\tfunction revealOutcome(uint256 gameId) public {\n\t\tGame storage game = games[gameId];\n\n\t\trequire(\n\t\t\tmsg.sender == game.challenger,\n\t\t\t\"Only the challenger can reveal the outcome\"\n\t\t);\n\t\trequire(!game.isFinished, \"The game is already finished\");\n\n\t\tgame.challengerFormation = challenger_formation[gameId];\n\n\t\tGameResult memory result = determineGameResult(game);\n\t\tgameResults[gameId] = result;\n\n\t\tgame.isFinished = true;\n\n\t\taddress winner = determineWinner(game, result);\n\t\tpayoutWinners(game, winner);\n\n\t\temit GameFinished(gameId, msg.sender, game.opponent);\n\t}\n\n\tfunction opponentClaimTimelock(uint256 gameId) public {\n\t\tGame storage game = games[gameId];\n\n\t\trequire(\n\t\t\tmsg.sender == game.opponent,\n\t\t\t\"Only the opponent can claim the timelock\"\n\t\t);\n\t\trequire(\n\t\t\tblock.number > game.blockNumber + timelockBlocks,\n\t\t\t\"Opponent can claim timelock only after timelockBlocks have passed\"\n\t\t);\n\n\t\tgame.isFinished = true;\n\t\tpayoutWinners(game, game.opponent);\n\n\t\temit GameFinishedByTimelock(gameId, msg.sender, game.challenger);\n\t}\n\n\t///////////////\n\t// HELPER FUNCTIONS //\n\t///////////////\n\n\tfunction determineGameResult(\n\t\tGame storage game\n\t) private view returns (GameResult memory) {\n\t\tGameResult memory result = GameResult({\n\t\t\tgoalsHomeTeam: 0,\n\t\t\tgoalsAwayTeam: 0\n\t\t});\n\n\t\t// Player memory homeGoalkeeper = players[game.challengerFormation[1]];\n\t\t// Player memory awayGoalkeeper = players[game.opponentFormation[1]];\n\t\tbytes32 prevRandao = blockhash(block.number - 1);\n\t\tuint256[] memory randomValues = extractRandomValues(10, prevRandao);\n\t\tfor (uint i = 1; i < game.challengerFormation.length; i++) {\n\t\t\tPlayer memory homePlayer = players[game.challengerFormation[i]];\n\t\t\tPlayer memory awayPlayer = players[\n\t\t\t\tgame.opponentFormation[game.challengerFormation.length - i]\n\t\t\t];\n\t\t\tuint256 totalspeed = homePlayer.speed + awayPlayer.speed;\n\t\t\tuint256 randomSpeed = uint256(prevRandao) % totalspeed;\n\t\t\tif (homePlayer.speed > randomSpeed) {\n\t\t\t\t// Home player attacks\n\t\t\t\tif (homePlayer.attack > randomValues[i - 1]) {\n\t\t\t\t\tresult.goalsHomeTeam++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (awayPlayer.attack > randomValues[i - 1]) {\n\t\t\t\t\tresult.goalsAwayTeam++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tfunction extractRandomValues(\n\t\tuint numberOfValues,\n\t\tbytes32 prevRandao\n\t) public pure returns (uint[] memory) {\n\t\trequire(numberOfValues > 0, \"Number of values must be greater than 0\");\n\t\tuint[] memory randomValues = new uint[](numberOfValues);\n\t\tuint256 randValue = uint256(prevRandao);\n\n\t\tfor (uint i = 0; i < numberOfValues; i++) {\n\t\t\trandomValues[i] = randValue % 100;\n\t\t\trandValue = randValue / 256; // Shift right by 2 hex digits\n\t\t}\n\n\t\treturn randomValues;\n\t}\n\n\tfunction determineWinner(\n\t\tGame storage game,\n\t\tGameResult memory result\n\t) private view returns (address) {\n\t\tif (result.goalsHomeTeam > result.goalsAwayTeam) {\n\t\t\treturn game.challenger;\n\t\t} else if (result.goalsHomeTeam < result.goalsAwayTeam) {\n\t\t\treturn game.opponent;\n\t\t}\n\t\treturn address(0); // It's a draw\n\t}\n\n\tfunction payoutWinners(Game storage game, address winner) private {\n\t\tif (winner == address(0)) {\n\t\t\trequire(\n\t\t\t\tfootballCoin.transfer(game.challenger, game.wagerAmount),\n\t\t\t\t\"Transfer to challenger failed\"\n\t\t\t);\n\t\t\trequire(\n\t\t\t\tfootballCoin.transfer(game.opponent, game.wagerAmount),\n\t\t\t\t\"Transfer to opponent failed\"\n\t\t\t);\n\t\t} else {\n\t\t\tuint256 totalPot = game.wagerAmount * 2;\n\t\t\trequire(\n\t\t\t\tfootballCoin.transfer(winner, totalPot),\n\t\t\t\t\"Transfer to winner failed\"\n\t\t\t);\n\t\t}\n\t}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index 70b0e88..e4caa0e 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -1565,7 +1565,7 @@ const deployedContracts = { }, }, FootballGame: { - address: "0x492bD2595393678F4E7ef2a2D3136860D4d83378", + address: "0x0238E08bFCd6252c70c3A1C30eeD44D70fe53156", abi: [ { inputs: [ @@ -1595,7 +1595,13 @@ const deployedContracts = { { indexed: true, internalType: "address", - name: "opponent", + name: "sender", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "recipient", type: "address", }, { @@ -1623,6 +1629,18 @@ const deployedContracts = { name: "gameId", type: "uint256", }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "recipient", + type: "address", + }, ], name: "GameFinished", type: "event", @@ -1636,6 +1654,18 @@ const deployedContracts = { name: "gameId", type: "uint256", }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "recipient", + type: "address", + }, ], name: "GameFinishedByTimelock", type: "event", @@ -1652,13 +1682,13 @@ const deployedContracts = { { indexed: true, internalType: "address", - name: "challenger", + name: "sender", type: "address", }, { indexed: true, internalType: "address", - name: "opponent", + name: "recipient", type: "address", }, {