IERC20 Transfer works well in test, but fail in integration

I am building a platform where user can create a reward (assign token to it) and generate a link where link user can get assess to some percentage of the token assign to the reward.
Reward creator can end the reward and get fund transferred back to his address.
I am also using the contract (address) to hold tokens, which at end of reward, would want to transfer remaining fund associated to the reward back to the reward creator.

Below is the end reward function

//withdraw amounts and close project
function closeProjectWithdrawTokens(uint256 projectID)
    RewardProject storage proj = rewardProjMapping[projectID];

    //transfer balance reward tokens to project owner
    TokenInfo[] storage rewards = rewardTokens[projectID];
    for (uint8 i = 0; i < rewards.length; i++) {
        TokenInfo storage reward = rewards[i];
        uint256 tempBalance = reward.balance;
        reward.balance = 0;
        //token is the address
        IERC20(reward.token).transfer(_msgSender(), tempBalance);

    //set reward project to inactive status
    proj.status = false;

    emit RewardProjectClose(_msgSender(), projectID);

This works very fine in test script as the user account increment on withdrawal, but in integration, no errors, the amount doesn’t leave the contract.

In integration, I receive the event accurately, showing the the id parameter passed is accurate.

Please what could be wrong?

1 Like

Hi @Chijioke_Agu,

Welcome to the community :wave:

I didn’t spot anything obvious, a likely issue would be having not enough tokens held by the contract.

You may want to try using Hardhats console.log to print out values in your function:

@abcoathup Thank you for the prompt reply, I am actually consoling the balance of the contract (address) in front end, as it is incrementing, but calling this function to send it out, I didn’t see the decrement, but the status of the reward changes (to false as suppose).
I am guessing if there is a problem with integration, this status won’t change, and transaction will be reverted.
Yet this works perfect in my test.
Please is there a work around to this design of holding token by a contract and later transfer to a user?
Thanks a lot

1 Like

Hi @Chijioke_Agu,

You can approve an allowance of tokens for your contract (instead of the contract holding them), the main thing is ensuring that the allowance is enough.

Please can I get a little more information on this or sample link? Thanks a lot

1 Like

Hi @Chijioke_Agu,

You can have a look at the Crowdsales in OpenZeppelin Contracts 2.x