Cannot use transferFrom, even though I have set allowance

Hi, no matter what I try, I am unable to call token.transferFrom without getting ERC20: transfer amount exceeds allowance - even though I have approved the allowance.

Code speaks better than words:


contract Strategy is ReentrancyGuard {
  IERC20 private  paymentToken;
  Token private  strategyToken;

  constructor(IERC20 _paymentToken, Token _strategyToken) {
    paymentToken = _paymentToken;
    strategyToken = _strategyToken;

  function deposit(uint256 amount) external payable nonReentrant {
    // Transfer payment token from msg.sender to contract
    paymentToken.transferFrom(msg.sender, address(this), amount);

In my test (this is where it fails):

import { expect} from "chai";
import { ethers } from "hardhat";
import { Strategy } from "../typechain/Strategy";
import { Token } from "../typechain/Token";

describe("Strategy", () => {
  let strategy: Strategy;
  let paymentToken: Token;
  let receivedStrategyToken: Token;
  before(async () => {
    const Strategy = await ethers.getContractFactory("Strategy");
    const TokenMock = await ethers.getContractFactory("Token");

    paymentToken = await TokenMock.deploy("Payment token mock", "PAYMOCK") as Token;
    receivedStrategyToken = await TokenMock.deploy("Received token mock", "RECEIVEMOCK") as Token;

    strategy = await Strategy.deploy(paymentToken.address, receivedStrategyToken.address) as Strategy;

  describe("Strategy contract", () => {
    it("It will return a strategy token when depositing", async () => {
      const [addr] = await ethers.getSigners();
      await, "1000");
      await paymentToken.increaseAllowance(addr.address, "1000");
      expect(await strategy.deposit(1));

As stated above, it complains with ERC20: transfer amount exceeds allowance - but I don’t know why, because I have increased the allowance?

This line paymentToken.transferFrom(msg.sender, msg.sender, amount); doesn’t make sense - you’re setting the msg.sender both as the sender and the recipient… Also, when you call deposit it is the Strategy contract which is doing the transfer … so the sender must approve the Strategy contract to transfer the amount

Oh darn. I was just playing around. It should be address(this). I will change the quesiton.

It seems the problem is because I need to call increaseAllowance for the contract address. Can someone explain why? You see, the reason I am getting confused is when I look at the source of transferFrom

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);

        return true;

Specifically, the error that is causing things to fail are these lines:

uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");

If I am not mistaken, the recipient is the contract, however nothing is being checked for the recipient. Perhaps _msgSender() is the contract address in this capacity, but why (since it returns msg.sender as well)?