I'm trying to call a function with no parameters and send Ether to it. I'm using React, Hardhat, and Ethersjs. The smart contract looks like this.
pragma solidity ^0.7.6;
contract EtherCoinFlip {
uint256 etherWinnings;
struct EtherCoinFlipStruct {
address payable betStarter;
uint256 startingWager;
address payable betEnder;
uint256 endingWager;
uint256 etherTotal;
address payable winner;
address payable loser;
}
uint256 numCoinFlips = 300;
mapping(uint256 => EtherCoinFlipStruct) EtherCoinFlipStructs;
// Emit the event
event EtherCoinFlipped(uint256 indexed theCoinFlipID);
// Start the Ether coin flip
function newPureCoinFlip() public payable returns (uint256 coinFlipID) {
coinFlipID = numCoinFlips++;
EtherCoinFlipStructs[coinFlipID] = EtherCoinFlipStruct(
msg.sender, //address payable betStarter;
msg.value, // uint256 startingWager;
msg.sender, // address payable betEnder;
msg.value, // uint256 endingWager;
0, // uint256 etherTotal;
msg.sender, // address payable winner;
msg.sender // address payable loser;
);
emit EtherCoinFlipped(coinFlipID);
}
event EtherCoinFinishedFlip(address indexed winner);
function endPureCoinFlip(uint256 coinFlipID)
public
payable
{
require(coinFlipID == coinFlipID);
EtherCoinFlipStruct memory c = EtherCoinFlipStructs[coinFlipID];
c.betEnder = msg.sender;
c.endingWager = msg.value;
c.etherTotal = c.startingWager + c.endingWager;
uint256 finalVerdict = block.number +
block.timestamp +
msg.value +
block.difficulty +
block.gaslimit +
tx.gasprice +
1;
if ((finalVerdict % 2) == 0) {
c.winner = c.betStarter;
} else {
c.winner = c.betEnder;
}
c.winner.transfer(c.etherTotal);
emit EtherCoinFinishedFlip(c.winner);
}
}
The function in my App looks like this.
async function startCoinFlip() {
if (typeof window.ethereum !== 'undefined') {
await requestAccount()
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contract = new ethers.Contract(ECFAddress, EtherCoinFlip.abi, signer);
let tx = {
to: ECFAddress,
value: ethers.utils.parseEther(wager),
}
let tx2 = await signer.sendTransaction(tx);
// call the coinFlip function and send the wager in ether to the contract
const coinFlip = await contract.startCoinFlip()
coinFlip.wait();
tx2.wait();
console.log(`You started the wager with ${wager} ETH`);
}
}
I'm using state to transfer the wager variable like this.
const [wager, setWager] = useState() // amount of ether to send to Eth coin flip
And it all comes together in the JSX like this.
<h1>Ether Coin Flip</h1>
<h3>Send your ETH to this contract with a 50/50 shot to double it!</h3>
<button value={wager} onClick={startCoinFlip}>Start the coin flip!</button>
<input onChange={e => setWager(e.target.value)} placeholder="Send your ETH"/>
<br />
I've rewritten the smart contract. Changed the wager type. Send the Ether in a separate function. None worked. Here's the error I get.
Unhandled Rejection (Error): cannot estimate gas; transaction may fail or may require manual gas limit (error={"code":-32000,"message":"execution reverted"}, method="estimateGas", transaction={"from":"0x0a337D5f4E3ba3f9eb413884d803dA8F1C8a9981","to":"0x16592Aecc7a43181889Ed6D6BDa8d813366B2381","value":{"type":"BigNumber","hex":"0x0de0b6b3a7640000"},"accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.4.5)