-game.sol //使用固体合同
pragma solidity ^0.8.0;
contract HeadOrTail{
address public owner;
event GameStarted(address indexed player1, address indexed player2, uint256 betAmount);
event GameEnded(address indexed winner, address indexed loser, uint256 totalPrize);
struct Game {
address payable player1;
address payable player2;
uint256 betAmount;
bool isActive;
}
mapping(uint256 => Game) public games;
uint256 public gameIdCounter;
constructor() {
owner = msg.sender;
}
function startGame(address payable _player1, address payable _player2) external payable {
require(_player1 != _player2, "Players cannot be the same");
require(msg.value % 2 == 0, "Total bet amount must be evenly divisible by 2");
uint256 gameId = gameIdCounter++;
uint256 betAmount = msg.value;
games[gameId] = Game(_player1, _player2, betAmount, true);
emit GameStarted(_player1, _player2, betAmount);
}
function resolveGame(uint256 gameId) external {
Game storage game = games[gameId];
require(game.isActive, "Game is not active");
uint256 randchoice = uint256(
keccak256(abi.encodePacked(block.timestamp, block.difficulty, msg.sender))
) % 2;
address payable winner;
address payable loser;
if (randchoice == 0) {
winner = game.player1;
loser = game.player2;
} else {
winner = game.player2;
loser = game.player1;
}
uint256 totalPrize = game.betAmount * 2;
game.isActive = false;
(bool sent, ) = winner.call{value: totalPrize}("");
require(sent, "Failed to transfer funds");
emit GameEnded(winner, loser, totalPrize);
}
}
Scripts/play_game.js
const hre = require("hardhat");
async function main() {
// Hardcoded player addresses (Replace with actual addresses)
// 0x1E7C116c770dCF79De5285d88b9d866Eac0Bf0B6
const player1 = "0x71780b13dEE6368508937Ce6C0FAB2cec63b376";
const player2 = "0xB91ebe10ec10EbBc566BF80E06a3c54D13383F4";
// Get signers (deployer will be used for deployment)
const [deployer] = await hre.ethers.getSigners();
// Deploy the contract
const HeadOrTail = await hre.ethers.getContractFactory("HeadOrTail");
const game = await HeadOrTail.deploy();
await game.deployed();
console.log(`Contract deployed to: ${game.address}`);
// Each player sends 1 ETH as a bet
const betAmount = hre.ethers.utils.parseEther("0.0001");
// Start the game (Use deployer or a specific signer)
const tx = await game
.connect(deployer)
.startGame(player1, player2, { value: betAmount });
await tx.wait();
console.log(`Game started between ${player1} and ${player2}`);
// Resolve the game
const tx1 = await game.connect(deployer).resolveGame(0);
await tx1.wait();
console.log(tx1);
console.log(`Game resolved!`);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
-hardhatconfig.js使用sepolia网络
require("@nomiclabs/hardhat-waffle");
require("dotenv").config();
module.exports = {
solidity: "0.8.0",
networks: {
hardhat: {
chainId: 31337,
},
localhost: {
chainId: 31337,
gasPrice: 875000000,
},
sepolia: {
url: process.env.SEPOLIA_RPC_URL,
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
saveDeployments: true,
chainId: 11155111,
},
localhost1: {
url: "http://127.0.0.1:7545",
chainId: 5777,
gasPrice: 20000000000,
},
},
namedAccounts: {
deployer: {
default: 0,
1: 0,
},
player: {
default: 1,
},
},
};
我试图使用
运行流动yarn hardhat run scripts/play_game.js --network sepolia
eRror:
reason: 'execution reverted: Failed to transfer funds',
code: 'UNPREDICTABLE_GAS_LIMIT',
method: 'estimateGas',
transaction: {
from: '0x1E7C116c770dCF79De5285d88b9d866Eac0Bf0B6',
to: '0xD50e52a1f81523f1B0625B3Ec66138ce38DC8d77',
data: '0xb7a5a5b60000000000000000000000000000000000000000000000000000000000000000',
accessList: null
},
error: ProviderError: execution reverted: Failed to transfer funds
在您的合同中,恢复发生在解决方案中的这一行中:
Require(发送,“未能转让资金”);.call {value:totalPrize}(“”)未能转移资金,导致交易恢复。
转移失败,因为合同没有足够的ETH余额将全面派发给获胜者。
在play_game.js,您可以以0.0001 eth的Betamount调用StartGame,但这仅由Deployer发送。合同假设两个玩家都贡献了相等的投注,但是您的脚本并未模拟玩家1,并且玩家2单独发送资金。合同应明确要求每个玩家发送他们的下注,而不是依靠一个味精。 我希望它能有所帮助。