I'm writing a simple airdrop contract in which user will register himself using register(), and his address will be added to an array registered[].

After the registration period is over, admin (who has all the tokens) will run fn setTokenAmount() by way of which he will set the token (contract name FUDX, from file FUDXToken.sol) amount to be given for free and wil also approve each address to withdraw from his account.

Next, user(s) will run claimAirdrop() for getting the tokens. But everytime, a user runs the fn, it gives an error saying allowance is not available.

Can somebody pl suggest the remedy ?

// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
import "./FUDXToken.sol";
contract AirdropFudx is FUDX  {
    IERC20 private token;
     constructor (FUDX _token) {
        (admin) = payable(msg.sender);
        token  = _token;
     address[]  registered;
     uint256 public count;
     function register() external {
     modifier onlyOwner{
      require (msg.sender == admin, "Only Admin");
     uint256 tokenAmount;
     function setTokenAmount(uint256 _tokenamount) external onlyOwner {
         tokenAmount = _tokenamount;
         uint256  num = registered.length;
//         approve(address(this), num*tokenAmount);
         for( uint i=0; i<registered.length; i++) {
            approve(registered[i], tokenAmount);  
     function claimAirdrop() external returns(bool success) {
         token.transferFrom(admin, msg.sender, tokenAmount);    
         return true;

1 Answer 1


There are at least a couple of mistakes:


You are inheriting from FUDX and receive FUDX in the constructor. So it is likely you have two unrelated copies of FUDX. Then you call approve from the first

approve(registered[i], tokenAmount);  

and transferFrom from the second.

token.transferFrom(admin, msg.sender, tokenAmount);    

Make sure you have a single copy.


Making the user admin call setTokenAmount isn't authorizing user to withdraw from their account.

Instead it authorizes registered[i] to withdraw tokens from the contract

approve(registered[i], tokenAmount);  

It is not possible for a function to authorize a third party to withdraw from the sender.

You could make the contract withdraw the total.

function setTokenAmount(uint256 _tokenamount) external onlyOwner {
     tokenAmount = _tokenamount;
     uint256 num = registered.length;
     transferFrom(admin, address(this), _tokenAmount * num);
     for (uint i=0; i<num; i++) {
        approve(registered[i], _tokenAmount);  

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.