1

My contract does like this;

pragma solidity 0.6.2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./IDTToken.sol";

contract Stacking is Ownable{

    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    IDTToken stk = new IDTToken();
    mapping(uint256 => mapping(address => uint256)) public stackers;
    mapping(address => uint256) public poolBalance; 

    event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
    event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);

    struct PoolInfo {
        IERC20 tokenStack;           
        uint256 allocPoint;       
        uint256 lastRewardBlock; 
        uint256 accIDTPerShare; 
        }

    function deposit(uint256 _amount, uint256 _id) public payable {
        PoolInfo storage pool = poolInfo[_id];
        updatePool(_id);
        stackers[_id][msg.sender] = stackers[_id][msg.sender].add(_amount); 
        pool.tokenStack.safeTransferFrom(address(msg.sender), address(this), _amount);
        emit Deposit(msg.sender, _id, _amount);
         }

    function getERCapprove(IERC20 _token, address _spender, uint256 _value) public returns (bool){
        
        return _token.approve(_spender, _value);
        }
}

In the front end;

export const stackToken = async (stacking, token, account, amount, id, web3) => {
amount = web3.utils.toWei(amount, 'ether')
await stacking.methods.getERCapprove(token, stacking.options.address, amount).send({ from: account 
}).on('transactionHash',(hash) => {
  console.log(hash)
  stacking.methods.deposit(amount,id).send({from : account})
  })  
}

So when I approve the token it seams to be working. I receive a transaction hash from that call.

But the call for the transfer is causing an error.

If I make the deposit with a token that is not using safeERC, just a plain erc20 standard. I get the following error;

VM Exception while processing transaction: revert SafeERC20: low-level call failed

If I make the call to a token that uses safeERC I get the following error;

VM Exception while processing transaction: revert ERC20: transfer amount exceeds allowance

So I'm not sure if it's the approval or the transfer that isn't working

1
  • Is it possible that the approve function cannot be called from and by the contract to the token contract? If I make the call straight from to token contract it is working. Not with the external getERCapprove function. Which would make sense since otherwise I could get an address approved from a contract call instead of the real owner. Commented Nov 9, 2020 at 1:20

1 Answer 1

1

Let's see this function :

   function getERCapprove(IERC20 _token, address _spender, uint256 _value) public returns (bool){
    
    return _token.approve(_spender, _value);
    }

Here the Stacking contract approves _spender for _token. What you are looking for is the opposite : the user approves the Stacking contract to let it transfer his tokens in the deposit method.

In order to do this, the user has to interact directly with the token contract (pool.tokenStack) and call approve (the call must not come from the Stacking contract). Then you should be able to execute this line in the deposit function :

        pool.tokenStack.safeTransferFrom(address(msg.sender), address(this), _amount);

Also take a look at this, which is similar to your issue : Approve contract to withdraw funds from users's wallet.

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.