I am creating a crowdfunding dApp and am trying to figure out why a revert error is being called on the pledgeToCampaign
function every time I click a button to pledge ether. I'll lay out the error, my React code, and Solidity code for the function being called.
Here is the full error I get when I click the "Pledge" button that calls onclick={pledgeToCampaign}
:
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: Has ended", method="estimateGas", transaction={"from":"0x90BadE35Da052450B01e99b38Cbb550BC3f1dD58","to":"0x882978f7Afef5bc38c73461f4Bf096e5dF03Ef5C","data":"0x1f6dbc500000000000000000000000000000000000000000000000000000b5e620f48000","accessList":null}, error={"code":-32603,"message":"execution reverted: Has ended","data":{"originalError":{"code":3,"data":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000948617320656e6465640000000000000000000000000000000000000000000000","message":"execution reverted: Has ended"}}}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.7.2)
at Logger.makeError (index.ts:271:1)
at Logger.throwError (index.ts:284:1)
at checkError (json-rpc-provider.ts:79:1)
at Web3Provider.<anonymous> (json-rpc-provider.ts:644:1)
at Generator.throw (<anonymous>)
at rejected (json-rpc-provider.ts:1:1)
The revert error Has ended
doesn't make any sense because the campaign I am trying to pledge to is active and the end date isn't for another month. I know that the pledgeTo
function on the smart contract works properly because on Etherscan I can pledge to this same campaign ID without an error.
Here is the Solidity code just in case:
// Function to pledge to a campaign
function pledgeTo(uint _id) external payable {
Campaign storage campaign = campaigns[_id];
require(block.timestamp >= campaign.startAt, "Hasn't started");
require(block.timestamp <= campaign.endAt, "Has ended");
// Prevent reentry
campaign.pledged += msg.value;
pledgedAmount[_id][msg.sender] += msg.value;
// Emit Pledge
emit Pledge(_id, msg.sender, msg.value);
}
My theory is: I am not properly passing the campaign ID to the pledgeToCampaign
function. Meaning it's trying to pledge to the 0
campaign, which has obviously expired. Instead of the campaign that I would be currently trying to pledge to, which in this case is 6
.
Here is my React function to call the writeable function pledgeTo
from the smart contract:
// I separated all the writable functions in a separate configs file to export
// Imports for ethers and Contract ABI
// Pledge to a campaign
export async function pledgeTo(signer, amount) {
const factory = new ethers.Contract(contractAddress, CrowdGaming.abi, signer);
return factory.pledgeTo(amount);
}
I believe my error is I need to pass an id
as an argument/value because on Etherscan, I have to pass an id
and the amount
in ether in order to submit the pledged amount to the campaign. But I'll explain why that doesn't work for me:
On my front-end, here is how I set up the pledgeToCampaign
function:
// imported the pledgeTo function from configs
// Pledge to campaign
async function pledgeToCampaign() {
const amount = ethers.utils.parseEther(
document.getElementById("eth").value,
"ether"
);
try {
const tx = await pledgeTo(signer, amount);
setTxHash(tx.hash);
console.log(tx.hash);
} catch (err) {
console.log(err);
setErrMsg(`Uh oh, an error occurred!`);
}
}
I have an input field for someone to enter an id
number and then the code properly displays that campaign.
// Get campaign by ID
async function getCampaigns() {
const id = document.getElementById("id").value;
// ethers contract METHODS
const campaign = await contract.campaigns(id);
setCampaign(campaign);
}
But when I try to add const id = document.getElementById("id").value;
into the pledgeToCampaign
function, specifically at the line:const tx = await pledgeTo(signer, id, amount);
, I get an error that says there are 1 too many arguments, as it expects 2.
When I remove the signer
from both the pledgeTo
and the pledgeToCampaign
functions, I get an error that says requires signer
.
So to summarize, I believe my issue lies in not properly calling the right id
into the either the pledgeTo
and/or pledgeToCampaign
functions, as it's probably just trying to pledge to campaign 0
every time.
If anyone could help me solve this that would be great!