I am learning how to create full stack dApps with Hardhat, Solidity and React. I am currently creating a crowdfunding dapp and am trying to tie call the launchCampaign function from my smart contract on the front end with a button after a user fills out a campaign field.
I'll include the function code, the error code and my react code to call the function
Here is the error code:
Error when creating a contract: Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (reason="execution reverted", method="estimateGas", transaction={"from":"0xD6D7fE937a64dE974923e2f80b44DA3B18BdCc13","to":"0x4d075cBE13Be39d97c5D786958Dc0C167f59FAD9","data":"0xf00702a100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000000000006413e4580000000000000000000000000000000000000000000000000000000064140b68000000000000000000000000000000000000000000000000000000000000000b4d792063616d706169676e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000754657374696e6700000000000000000000000000000000000000000000000000","accessList":null}, error={"code":-32000,"message":"execution reverted"}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.7.2)
Here is React codes I have created:
From my configs file:
//Contract address
const contractAddress = "0x4d075cBE13Be39d97c5D786958Dc0C167f59FAD9";
// Create new campaign -- function comes from the smart contract
export async function launchCampaign(
signer,
title,
description,
goal,
startAt,
endAt
) {
const factory = new ethers.Contract(contractAddress, CrowdGaming.abi, signer);
return factory.launchCampaign(title, description, goal, startAt, endAt);
}
To display on the create a campaign page (I have set up a web3 provider, useState's and imported the function above properly):
async function newContract() {
// The variables here get data from input fields in the return section
const title = document.getElementById("title").value;
const description = document.getElementById("description").value;
const goal = ethers.utils.parseEther(
document.getElementById("goal").value,
"ether"
);
const startAt = document.getElementById("startAt").value;
const endAt = document.getElementById("endAt").value;
try {
const tx = await launchCampaign(
signer,
title,
description,
goal,
startAt,
endAt
);
setTxHash(tx.hash);
console.log(`Tx hash: ${tx.hash}`);
} catch (err) {
console.log(`Error when creating a contract: ${err}`);
}
The function from the Sol file:
// Function to launch a campaign - public return the campaign ID
function launchCampaign(string calldata _title, string calldata _description, uint _goal, uint256 _startAt, uint256 _endAt) external {
// Require campaign length to be a future date
require(_startAt >= block.timestamp, "Invalid start date");
require(_endAt >= _startAt, "Invalid end date");
require(_endAt <= block.timestamp + 30 days, "Cannot go past 30 days");
require(_goal > 0, "Goal must be greater than 0");
require(bytes(_title).length <= 50, "Title too long");
require(bytes(_description).length <= 2000, "Description too long");
// Add to totalCampaign variable
totalCampaigns++;
// Set new variables for campaign
campaigns[totalCampaigns] = Campaign({
owner: msg.sender,
title: _title,
goal: _goal,
pledged: 0,
description: _description,
startAt: _startAt,
endAt: _endAt,
claimed: false
});
// Emit Launch
emit Launch(totalCampaigns, msg.sender, _title, _goal, _description, _startAt, _endAt);
I know that the smart contract works, as I am able to launch a campaign effectively on Goerli etherscan and have it emit the event properly.
I believe the error is related to me not properly setting up the Signer, but the etherjs docs isn't as clear to me as it should be!
If anyone could point me in the right direction that would be amazing
SOLVED
I removed the length requirements for the strings and everything works properly now. Instead of implementing it there, I will implement a restriction on the front end of the dApp!