Error: Revert when using ERC20 transferFrom

I build a contract, where a user can deposit a custom token using the createStake function like that:

contract StakingRewards  {
    
    IERC20 token;

    //...

    constructor(address _tokenAddress){
       token = ERC20(_tokenAddress);
    } 

    //...

    function createStake(uint256 _stake) public {
        require(token.transferFrom(msg.sender, address(this), _stake)); // <-- This seems to be the problem with truffle test
        if(stakes[msg.sender] == 0) _addStakeHolder(msg.sender);
        stakes[msg.sender] = stakes[msg.sender].add(_stake);
    }

}

When using the console truffle console --network development everything work. as expected:

  • I first approve the token allowance for the staking rewards contract like that: token.approve(StakingRewards.address, "100000000000", {from: "0x232....."})
  • and then call createStake: createStake("100000000000", {from: "0x232...."}) and it’s working.

When i’m trying to test it, i’m having some issue, it keep reverting: Error: Returned error: VM Exception while processing transaction: revert
This is the code i’m using for the test:

   //... 

const customToken = artifacts.require("CustomToken");
const StakingRewards = artifacts.require("StakingRewards");

contract('StakingRewards', ([owner, staker1,]) => {
  beforeEach( async () => {
    customToken = await CustomToken.new("1000000000000000000000000");

     //...

    stakingRewards = await StakingRewards.new(CustomToken.address);
    await customToken.transfer(staker1, "5000000000000000000000");
  });

  it("Should create/add stake correctly ", async () => {
    const stakeAmount = "10000000000000000000";
    await customToken.approve(StakingRewards.address, stakeAmount, {from: staker1 });
    await stakingRewards.createStake(stakeAmount, { from: staker1 }); // <--- This keep failling, with "Error VM Exception while processing transaction: revert"
   
    //...
  });
}); 

Can i have some help ? Why this test keep failing ? What did i got wrong ?

Thanks

Hey, welcome!

I think your steps are right,

1. token.approve(staking.address, amount);
2. staking.createStake();

And yes, I also think the problem is at this line: require(token.transferFrom(msg.sender, address(this), _stake)); I think maybe your staking token is not a standard ERC20 token, for example, USDT, is not a standard ERC20 token, so it does not have a return value for the function transferFrom, so even though usdt.transferFrom() succeed, this require will fail, so I think you had better use a compatible way, such as using the library of OpenZeppelin: SafeERC20.sol, and it can be:

using SafeERC20 for IERC20; // or using SafeERC20 for ERC20;

function createStake(uint256 _stake) public {
    token.safeTransferFrom(msg.sender, address(this), _stake));
}
2 Likes

Hey, Thanks for your reply.
I tried but it still not working, i’m getting: Error: Returned error: VM Exception while processing transaction: revert SafeERC20: low-level call failed -- Reason given: SafeERC20: low-level call failed.

A little weird, so can you share me with a failed transaction?