-1

i am building an escrow smart contract. I would like the contract to accept only ERC20 token. USDC OR USDT.

Is there a way to inlcude this in my deposit function ? Similar questions have been asked but they assume that i have already created a custom erc20 token

1
  • ERC20 is a token standard. Many tokens are built a top of it. Do you want create deposit functions for specific ERC20 tokens like USDT. Or do you want your contact to accept all ERC20 tokens but not any of ERC721 (for example)
    – Sky
    Dec 10, 2022 at 7:41

2 Answers 2

1

you should call "transferFrom" function in erc20 standard from your contract. before this function, user has to call "approve" function. you should consider a mapping for acceptable ERC20.

pragma solidity 0.8.17;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract ReceiverERC20 is Ownable {

mapping(address => bool) public approvedERC20Address;

modifier onlyApprovedERC20 (address ERC20Address){
    require (approvedERC20Address[ERC20Address],"ReceiverERC20 : only transfer from approved erc20 is accepted");
    _;
}

event Deposited (uint TransactionID ,address Sender, address ERC20Address , uint value );

function changeERC20State (address ERC20Address,bool state) external onlyOwner()  {
    approvedERC20Address[ERC20Address] = state;
}
 // before this, user must call approve this address
function depositERC20 (uint transactionID , address ERC20Address, uint value)  external onlyApprovedERC20 (ERC20Address){
    IERC20(ERC20Address).transferFrom(msg.sender, address(this), value);
    emit Deposited(transactionID,msg.sender,ERC20Address,value);
}

}
0

If I understand correctly, you need to write a contract that can only accept approved tokens. There are several ways to write such a contract, for example:

pragma solidity ^0.8.0;

import { IERC20 } from "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";

contract MyContract {
  // Import the ERC20 interface
  IERC20 public token;

  constructor(address _tokenAddress) public {
    // Set the address of the ERC20 token contract
    token = IERC20(_tokenAddress);
  }

  function receivePayment(address _from, uint256 _value) public {
    // Require that the payment is made with an ERC20 token
    require(token.transferFrom(_from, address(this), _value), "ERC20: transfer failed");
  }
}

So when you deploy this contract you specify in arguments what ERC20 token it should use. The receivePayment function then requires that the payment is made with an ERC20 token by calling the transferFrom function on the token instance.

This is a basic contract that can be upgraded to accept several different tokens.

Let's assume that we want to be able to accept several tokens at once:

pragma solidity ^0.8.0;

import { IERC20 } from "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";

contract MyContract {
  // Import the ERC20 interface
  IERC20 public token;

  // Array of accepted ERC20 token addresses
  address[] public acceptedTokens;

  constructor(address[] memory _acceptedTokens) public {
    // Set the array of accepted ERC20 token addresses
    acceptedTokens = _acceptedTokens;
  }

  function receivePayment(address _from, uint256 _value, address _token) public {
    // Require that the payment is made with an accepted ERC20 token
    require(isAcceptedToken(_token), "ERC20: token not accepted");

    // Set the token instance to the provided token address
    token = IERC20(_token);

    // Require that the payment is made with the correct amount of tokens
    require(token.transferFrom(_from, address(this), _value), "ERC20: transfer failed");
  }

  function isAcceptedToken(address _token) public view returns (bool) {
    // Check if the provided token address is in the acceptedTokens array
    for (uint256 i = 0; i < acceptedTokens.length; i++) {
      if (acceptedTokens[i] == _token) {
        return true;
      }
    }

    return false;
  }
}

Here we have the variable acceptedTokens, which also in the constructor sets what tokens can be used in the contract.

There is also a special helper function called isAcceptedToken, which allows you to check whether the token can be used or not

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.