I'm wanting to accept stablecoin transfers and currently have independent operations to handle the payments yet concerned this will lead to faulty interactions, lost funds, and incorrect execution:

    function depositDAI() external payable {
        require(msg.value >= amount, "Insufficient funds");
        transferFunds(DAI, 10**18);

    function depositUSDC() external payable {
        require(msg.value >= amount, "Insufficient funds");
        transferFunds(USDC, 10**6);
    function depositUSDT() external payable {
        require(msg.value >= amount, "Insufficient funds");
        transferFunds(USDT, 10**6);

Would it be possible to handle these operations in a single function? I would like to check:

  1. the ERC20 is supported
  2. amount of ERC20 is sufficient
  3. available for direct interaction with wallet

1 Answer 1


So lets begin from there that if you don't want to receive ETH your functions doesn't have to be payable.

For points 1) and 2) this code will help:

interface ERC20 {
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool);

contract Name {
    mapping(address -> bool) supportedStableCoins;
    mapping(address -> uint) minAmauntForSuportedStableCoin;

    function addCoin(address _coinAddress, uint _minAmount) external {
        require(supportedStableCoins[_coinAddress] == true, "Already added");
        supportedStableCoins[_coinAddress] = true;
        minAmauntForSuportedStableCoin[_coinAddress] = _minAmount;

    function deposit(address _coinAddress, uint _amount) external {
       require(supportedStableCoins[_coinAddress] == true)
       require(minAmauntForSuportedStableCoin[_coinAddress] <= _amount);
       require(ERC20(_coinAddress).transferFrom(msg.sender, address(this), _amount));

Note 1: In order to execute transferFrom the message sender first must have approved the _amount to the contract.

Note 2: You must have constructor and some modifiers to the addCoin function. You don't want every one to add coins to your contract.

Regarding point 3) if you provide front end functionality to make transaction everything would be out of the box.

  • Thanks for the great writeup! I'm still having difficulty understanding how this works: is _coinAddress under the deposit function the address of the sender's wallet or would the sender be enforced to send the token address? If the latter, would there be a way to infer the address to avoid having them specify the address of the token? Also, in regards to approve would that be a separate call or could it be added above transferFrom?
    – aug2uag
    Commented Oct 27, 2021 at 8:38
  • 1
    No, every stable coin DAI/USDC/USDT is also a contract, this contract have specific functions which are well known under the name of ERC20 interface also their contracts have address. _coinAddress is their contract's address Commented Oct 27, 2021 at 8:40
  • 1
    For eg here is the USDC contract - etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 Commented Oct 27, 2021 at 8:41
  • 2
    Here you can get a better idea for ERC20 tokens - medium.com/@jgm.orinoco/… Commented Oct 27, 2021 at 8:46
  • 1
    But you have registered the valid token address with theaddCoin and if the user send unregistered the function will revert Commented Oct 27, 2021 at 8:48

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.