Stake contract test but fail to transfer LPtoken to stake

I’m learning how to deploy a defi contract and following the step of deploying a series of contracts from yearn. All of the contract deployments are fine but the following test step of staking ycurvefi lp token into the reward contract is failed. The following are all the contracts addresses:
ycurvefi contract ->0x66e795d4cc98a823042456f9e1920236597f81d3
ycurevefireward contract ->0xF7F3dB45AD4558AF3331530Ab058Ef5A782318E4

:computer: Environment
I am using , metamask , solidity 0.5.16, remix to do the test.

:memo:Details
I’m not sure whether there is an issue with the contract rule. But I think I can stake some lp tokens at least. I have checked the topic of How to use a token transfer function into another function ? [ ERC20 ] But it can not answer my question. I think I’ve done token approval in advance and then start to stake token with the same account. but it still fails to send the lp token. I’m confused that whether I’ve done the right step to send ERC20 token or not.

:1234: Code to reproduce
The error message I got in remix interface is:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? gas required exceeds allowance (10000000) or always failing transaction
And the step I’ve done is:

  1. approve with account and amount in Ycurve.fi contract
  2. stake directly with the same account and amount in remix interface.
    function stake(uint256 amount) public {
        _totalSupply = _totalSupply.add(amount);
        _balances[msg.sender] = _balances[msg.sender].add(amount);
        y.safeTransferFrom(msg.sender, address(this), amount);
    }

    function stake(uint256 amount) public updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        super.stake(amount);
        emit Staked(msg.sender, amount);
    }

P.S the y is ycurvefi contract address.

I think the problem is simple. But cause I am a newer in smart contract that I don’t know where is the problem. Please help :sob:

1 Like

Answer the question by my own.
The mistake I took is approve the address of my own private account instead of the reward contract address.
After operating correctly, everything is gone fine.

1 Like

Hi @uua,

Glad you were able to resolve. Thanks for sharing an update :pray:.

I have a short Example on how to use ERC20 token in another contract

1 Like

Thanks for sharing! It’s helpful

1 Like

Another problem emerged when I try to get my reward. The error message is the same as what I’ve posted on this topic. Although I tried to approve the reward contract address on ycn contract, It didn’t work. As written in the following code, the reward will be transferred from ycn contract to the reward owner. I’ve checked the original code of ERC20, but I didn’t find the approve function in the process of transferring. So, I have no idea what’s happened this time.

    function getReward() public updateReward(msg.sender) {
        uint256 reward = earned(msg.sender);
        if (reward > 0) {
            rewards[msg.sender] = 0;
            ycn.safeTransfer(msg.sender, reward);
            emit RewardPaid(msg.sender, reward);
        }
    }

ycn contract address:0xa422Cba4a11bf7b6eE7a50F0963A3245970445d2

1 Like

Hi @uua,

If I understand correctly the reward contract (https://ropsten.etherscan.io/address/0xF7F3dB45AD4558AF3331530Ab058Ef5A782318E4#code) is meant to transfer earnt reward tokens (https://ropsten.etherscan.io/address/0xa422Cba4a11bf7b6eE7a50F0963A3245970445d2#code)

The issue appears to be that the reward contract doesn’t have any reward tokens (checking the token balance of the reward contract).

1 Like

Thanks! it works. I thought the reward contract will call the transfer function from the reward token contract. Could you please explain why I need to deposit some tokens in advance? In my opinion, the reward contract call the transfer function from the reward token contract should be fine.

1 Like

Hi @uua,

It is because the reward contract does a transfer, so the contract has to have enough tokens to transfer. (It calls SafeERC20.safeTransfer which calls IERC20.transfer)

ycn.safeTransfer(msg.sender, reward);

transfer

Moves amount tokens from the caller’s account to recipient .

1 Like

It makes sense, thanks again.

1 Like