I am trying to write a smart contract with a function that receives an ERC20 token (i.e.: DAI), but the transaction to call this function is always failing.
Let's assume I first record the ERC20 Contract address in a mapping where I can handle several tokens, but for this example, I just have 'DAI' as tokenName and assign its DAI contract address in Ropsten:
contractAddressERC20[tokenName] = 0xaD6D458402F60fD3Bd25163575031ACDce07538D;
I am also using an ERC20 interface from OpenZeppelin:
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Then, I have this function to receive ERC20 tokens. For the example, I would be passing 'DAI' as tokenName and 1 DAI (1000000000000000000)
function depositERC20Token(string memory tokenName, uint256 amount) public {
IERC20(contractAddressERC20[tokenName]).approve(address(this), amount);
IERC20(contractAddressERC20[tokenName]).transferFrom(_msgSender(), address(this), amount);
emit DepositERC20Token(tokenName, _msgSender(), amount);
}
However, calling this function is always failing. Not sure if the 'approve' function should be called directly from the DAI contract by the User, and then call the 'depositERC20Token' from my contract only with the 'transferFrom'. Isn't it possible to do the 'approve' and 'transferFrom' from my contract? If not, the User should execute 2 transactions, which is not that good from a UX perspective.
Is there a way to do the approve & transferFrom in one shot when calling this contract? I've heard of ERC777, but would prefer to keep ERC20 standard if possible.
*_msgSender() is equivalent to msg.sender, as defined in Context.sol from OpenZeppelin
_msgSender()
return, and what makes you think that you can transfer tokens from that address?