Transferring USDT from metamask to smart contract

I'm trying to transfer USDT tokens from my metamask account to another address(which is variable in smart contract) through a method call.

If I use transferFrom I'm getting an error saying the transfer amount exceeds the allowance. So I'm trying to understand what I'm doing wrong. I've tried giving allowance to msg.sender, address(this), usdtTokenAddress but nothing worked.

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

using SafeERC20 for IERC20;

contract Shop{
address usdtContractAddress;
address usdtWalletOfShop;
function approve(uint128 amount) public  {
            IERC20(usdtContractAddress).approve(address(this), amount);

    function order(uint128 amount) public {
        // IERC20((usdtContractAddress)).transfer(usdtWalletOfShop, amount);
        IERC20((usdtContractAddress)).transferFrom(msg.sender, usdtWalletOfShop, amount);
        usdtBalanceOfShop += amount;
        orderId += 1;
        emit Payment(msg.sender, amount, orderId);


Before executing shop.order(amount), you need to execute usdc.approve(shopAddress, amount).

And you need to do so using the same account for both transactions (regardless of whether that account is a wallet or a contract).

Needless to say, implementing function approve in your Shop contract is unnecessary.

Yes, I'm doing exactly like that. Do you mean I should call usdt.approve in the order method? Or I should call it outside the smart contract?

I'm not sure how to explain it any better than I already have, so I'll just repeat myself:

Before executing shop.order(amount), you need to execute usdc.approve(shopAddress, amount) using the same account for (signing) both transactions.

You should execute usdt.approve(shopAddress, amount) by your wallet, not by shop contract.
And approve function in shop contract is unnecessary.

Which is exactly what I wrote in my original answer, and in the one which followed it.

1 Like