I've got a question that I cannot seem to find an answer for, hoping the community can help (and this is my first post here so my apologies if this is the wrong question to ask in the first place).

I am trying to create a contract with a Payable function that only accepts a specific token, not ETH, as payment. I own both the token contract and this contract which is specifically created to accept payment for for that particular token.

Is this even possible? I found this as a possible solution:

Source: How do I create a crowdsale that only accepts a specific erc20 token?

contract Crowdsale {

        address owner;  
        mapping(address => uint256) balances;
        function Crowdsale(){
            owner = msg.sender;

        function acceptOnlyMyToken(address _yourTokenAddress, uint256 amount){
            address user = msg.sender;
            YourToken token = YourToken(_yourTokenAddress);

            //get the user's balance
            uint256 userBalance = token.balanceOf(user);
            //check user's balance
            if(userBalance >= amount){      
                token.transferFrom(user, owner, amount);        




Is it safe to assume the following with the code above?

  1. Replacing YourToken token = YourToken(_yourTokenAddress); with YourToken token = YourToken(address(0xABCD...)); with "0xABCD" being the address of my token which is in a separate contract should work.
  2. Specifying require(msg.value == 100 under the acceptOnlyMyToken(...) function would allow me to set the specific payment amount required.

Also, I don't see this function being called as "payable", does this matter? The reason is because I want to pass on variables as part of the function to do XYZ work as part of the contract logic, for which I receive a payment for in a specific amount of that token.

Any thoughts?

1 Answer 1


You don't use payable for non-protocol type of transfer. ERC20 isn't "protocol" because it is defined in a contract.

There is no way to detect ERC20 tokens that are blindly transferred to a contract. At best, the contract can check it's balance but it won't know who sent money, so this is no good.

uint myTokenBalance = IERC20(<tokenAddress>).balanceOf(address(this));

You're looking for the "approve and transferFrom" pattern. It goes like this:

  1. The user authorizes your contract to draw from the user's token balance.

  2. Then, the user calls a function in your contract that tries to pull the tokens in.

Step 2 looks like this:

function sendMe100() external {
  IERC20(<tokenAddress>).transferFrom(msg.sender, address(this), 100);
  // success

The foregoing assumes that the user has authorized the transfer by first calling the approve function in the ERC20 contract (step 1), but that is usually a front-end concern that is of no concern to your contract.

Hope it helps.

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.