0

I have a mapping uint256=>bool. I am giving projectId to see is it registered or not. I registered a project. I use chainlink automation for do something. But when i call checkuppkeep function for testing, mapping returns false but function returns true after registration. Basicly is_funding public view function returns true as it should be but in the contract _isFunding[projectId] mapping return false. What is going on?

_isFunding[projectId] = true;

  function checkUpkeep(
    bytes memory /* checkData */
)
    public
    view
    override
    returns (
        bool upkeepNeeded,
        bytes memory /* performData */
    )
{
    bool isFunded = _isFunding[projectId];
    bool timePassed = (block.timestamp -
        (projectToTime[projectId][time[projectId]])) > time[projectId];
    upkeepNeeded = (isFunded);
}
function getTimeleft(uint256 _projectID)
    public
    view
    returns (uint256 a, uint256 b)
{
    a = block.timestamp - projectToTime[_projectID][time[_projectID]];
    b = time[_projectID];
}
function is_funding(uint256 _projectID) public view returns (bool) {
        return _isFunding[_projectID];
    }

Hardhat test file :

it("return false if project hasnt submit", async () => {
      blockNumber = await ethers.provider.getBlockNumber();
      console.log(`Before ${blockNumber}`);
      await moveTime(s_fundingTime + 1);
      await moveBlocks(s_fundingTime + 1);
      blockNumber = await ethers.provider.getBlockNumber();
      console.log(`Before ${blockNumber}`);
      const { upkeepNeeded } = await governor.checkUpkeep([]);
      const { a, b } = await governor.getTimeleft(projectId);
      console.log(await governor.is_funding(projectId));
      console.log(a.toString(), b.toString());
      console.log(upkeepNeeded);
      // assert(!upkeepNeeded);

console of test result:

Before 226
Moving time...
Moved forward 61 seconds..
Moving blocks...
Before 287
true
121 60
false
3
  • Hi Furkan, I tried a similar code as yours and cannot reproduce the issue, and can you edit your question to post complete contract?
    – Frank Kong
    Commented Nov 11, 2022 at 7:35
  • hi Frank, i have updated code as a new answer below. Turns out we cant use checkUpKeep function like this. On my code projectId is a variable on contract. This was the my fault. So it was checking only the last index of projectId. Lets say i add 5 project. checkupkeep only checking 5th project. Not all of them. So i changed code like below. Commented Nov 12, 2022 at 9:42
  • Cool, it is always a good practice that checkUpkeep works as expected before registering upkeep.
    – Frank Kong
    Commented Nov 14, 2022 at 3:19

3 Answers 3

1

I came up like this. I will return data perfomData as projectId so we can work on that projectId on chain.

function checkUpkeep(
    bytes memory /* checkData */
)
    public
    view
    override
    returns (bool upkeepNeeded, bytes memory performData)
{
    for (uint i = 1; i <= projectId; i++) {
        bool isFunded = _isFunding[i];

        console.log("_isFunding= ", _isFunding[i], i);

        bool timePassed = (block.timestamp - (projectToTime[i][time[i]])) >
            time[i];
        upkeepNeeded = (isFunded && timePassed);
        if (upkeepNeeded) {
            performData = abi.encodePacked(i);
            break;
        }
    }
}

This is the my perfromUpKeep func.

 function performUpkeep(bytes calldata performData) external override {
    (bool upkeepNeeded, ) = checkUpkeep("");
    if (!upkeepNeeded) {
        revert FundProject__UpkeepNeeded();
    }
    uint256 ProjectId = uint256(bytes32(performData));
    _isFunding[ProjectId] = false;
    _isApporovedByDao[ProjectId] = false;

    if (projectFunds[ProjectId] > projectFundingGoalAmount[ProjectId]) {
        _ProjectFundingStatus[ProjectId] = ProjectFundingStatus.SUCCESS;
        uint256 fundsToSent = (projectFunds[ProjectId] * daoPercentage) /
            100;
        (bool success, ) = (projectOwnerAddress[ProjectId]).call{
            value: fundsToSent
        }("");
        if (!success) {
            revert FundProject__TransferFailed(projectFunds[ProjectId]);
        }

        emit projectSuccessfullyFunded(ProjectId);
    } else {
        _ProjectFundingStatus[ProjectId] = ProjectFundingStatus.FAILED;
        emit projectFundingFailed(ProjectId);
    }
}
1

Good, If one project has one time stamp then why to don't use a struct, instead of mapping of mapping. Struct ProjectsInfo {unit timestamp; book idfunded} Mapping (unit=>ProjectsInfo) projectToTime

Also, with this solution, if you want optimization (packing), better to reduce the size of timestamp, like uint248.

0

Based on your posted code, You call checkUpkeep without the parameter projectId.

4
  • yes i am. i have a projects. every project have their own time to trıgger. I want to trigger every project when its time. dont want to trigger specify projectId Commented Nov 10, 2022 at 8:47
  • yes i was. But i figure it out.my mistake is projectId is a variable in the contract. So when ever i call checkUpKepp or performUpKepp it will run function with last index of that projectId. So just last project will be check. Commented Nov 10, 2022 at 9:28
  • in fact, if you expect to have the same result with is_funding with parameter projectId. And the function checkUpkeep then imad you know it s missing the parameter. For your need, to ensure that a project is triggered when it's time. I need to get more information about projectToTime. Is it a mapping of mapping? Of course to make a check, I ll advice offchain, but if you cannot, I ll advice to change your architecture.
    – Aurel
    Commented Nov 10, 2022 at 9:38
  • yes its a mapping of mapping // projectId => projectFundingTime => timestamp of adding Commented Nov 10, 2022 at 9:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.