I am building a staking contract that accepts an ERC20 token set by the owner.

contract ECommerce {
    IERC20 token;
token = IERC20(**"I insert the token address here"**);

Here are some important functions:

Stake token

     function stake(uint256 _tokenamount) public returns(bool) {
           require(_tokenamount <= GetAllowance(msg.sender), "Please approve tokens before transferring");
           token.transferFrom(msg.sender, address(this), _tokenamount);
           return true;

Allowance checker

 function GetAllowance(address _tokenOwnerAdd) public view returns(uint256){
       return token.allowance(_tokenOwnerAdd, address(this));

I get the error with the unstake function:

unStake token

     function unstake(uint256 _tokenamount) public returns(bool) {
           require(_tokenamount <= UserTokenBalance[msg.sender], "You cannot unstake more than you staked");
           token.transferFrom(address(this), msg.sender, _tokenamount);
           return true;

The unstake function just says: "Error will be thrown in contract execution"

Yes, the contract does have gas.

Any help would be appreciated - thank you!

1 Answer 1


You can't have the user approve tokens to spend from your own contract. The user would have to sign a transaction to the token itself, calling approve with your contract address. (otherwise you could just steal all his coins..!)

Usually how it's done is that your front end will issue for the user 2 txs: one to the token to approve your contract, and second to your contract to pull the tokens.

Additionally, to use this approve-and-pull mechanism, you need to use token.transerFrom(msg.sender, address(this), amount). The way you're doing it - token.transfer(address(this), _tokenamount) - will transfer tokens from your contract to itself.

  • Amazing, thank you so much. I will test it now and get back to you Commented Nov 23, 2021 at 9:01
  • Ok, staking works now but unstaking still seems to be a problem - it throws an error. I did send Ether to the contract so there is gas - any advice? ''' function unstake(uint _tokenAmt) public returns (bool){ require(_tokenAmt <= userTokenBalance[msg.sender], you cannot unstake more than you have stakes): token.transferFrom(address(this), msg.sender, _tokenAmt); ... } ,,, Commented Nov 23, 2021 at 10:52
  • No, I cannot understand it like this. If you want you can make a new question with all the details (like you supplied all details in your original question) and then I might be able to help. Commented Nov 23, 2021 at 11:33
  • Hi, I updated this question Commented Nov 23, 2021 at 16:31
  • I would log UserTokenBalance[msg.sender] and make sure your balance is enough Commented Nov 24, 2021 at 1:04

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.