Creating a claimable Air Drop - Too many Addresses

I’m creating a function that will allow users to claim an Air Drop if they held another token in the past.

I’ve gathered up the list of the addresses and the amount of token they will get when they claim the airdrop.

The untested code is below, and I know of some problems it will have which I can deal with later on during testing.

// Air Drop Functions
    function airDropClaim() public {

        address claimer = _msgSender();

        uint256 amountToGiveClaimer = airDropTokensLeftToClaim[claimer];

        airDropTokensLeftToClaim[claimer] -= amountToGiveClaimer;   // reduces the amount left to claim

        approveInternal(ownerOfToken, claimer, amountToGiveClaimer);        // approves amount to claim from owner address
        transferFrom(ownerOfToken, claimer, amountToGiveClaimer);       // transfers the airdrop amount from the owner address to the claimer
        approveInternal(ownerOfToken, claimer, 0);        // sets the approved amount back to zero


        emit AirDropClaimed(claimer, amountToGiveClaimer);
    }

The real problem is that I have 2000 Addresses to air drop to.
I can’t store them all into a Mapping during the initialization of the contract because the contract size would be too big. I’ve already tried.

Can I store the list of addresses and their amounts off chain somewhere and then call the off chain data?

Should I create a separate contract that would hold some addresses, then call them from my own contract somehow?

Any advice on how to accomplish this would be welcome. The main goal is to have a function the user can use to claim their tokens by spending their own gas to claim.

So my approach ended up being that I had to make a function to assign these addresses.
I don’t think there is any other way to off chain it, I have to pay gas at some point in order to have addresses their proper airdrop amount in their mapping.

I used an onlyOwner function below which I called after deployment.

function initializeAirDropAddressesAndAmounts(address[] memory addressesToAirDrop, uint256[] memory amountsToAirDrop) external onlyOwner() {  
        for(uint i = 0; i < addressesToAirDrop.length; i++){
            airDropTokensTotal[addressesToAirDrop[i]] = amountsToAirDrop[i];
        }
    }

If anyone has a better approach let me know. This doesn’t cost too much gas for 2000 addresses, about $50 in ETH, and $10 in BNB.

I think you can have a look at UNI and 1inch, how did they make airdrop? I think they make it by MerkleTree

How much does it cost if you make the arguments calldata instead of memory?

I’m not too sure. I can try calldata in my upcoming tests.

When using the memory keyword, it turns out the cost is about
Total:
0.0306 ETH ~ $61.2 in ETH
0.0306 BNB ~ $12.24 in BNB

For 2000 addresses. So this is very affordable when doing my airdrop.

I’ll see if this makes it cheaper and post back here.

I’ll check on 1inch and see if they have a guide.
I tried to understand MerkleTree, but I was having trouble grasping it. Where do the addresses come from when using a MerkleTree? I can read the code, but I feel like I’m missing something.

This is where I was reading the code for it. It looks like trustlines did this too.

If you have a tutorial or a guide on it I’ll read up on it.

@martriay
Looks like it’s more expense to use calldata than memory.
0.005773641 ETH https://rinkeby.etherscan.io/tx/0x72c7e3e7c8c8984eb2d6e38c99fea215a1e4586b68639f738562a0994475893f
vs
0.000862974 ETH
https://rinkeby.etherscan.io/tx/0x40b68b3fc0bc5828f94d08a9a980856346be62f26b0e2ebc7e3ba8839cc2038f