Token Distribution – Best Way to Distribute Tokens

erc-20icosoliditytokens

If I create a token, and then want to distribute it to 1000 people, I am worried about the gas price of those transactions. Which is why I wanted to analyse the different options for distributing and their inherent costs.

option 1: function in token that distributes to an array of users

function distributeToken(address[] addresses, uint256 _value) onlyOwner {
     for (uint i = 0; i < addresses.length; i++) {
         balances[owner] -= _value;
         balances[addresses[i]] += _value;
         Transfer(owner, addresses[i], _value);
     }
}

source: Distribute token to multiple address

ELABORATIONG ON OPTION ONE: is it possible to use parameters with an array of 1000 different addresses? That would be a massively large parameter and I'm curious as to what the gas price would look like.

option 2: using an exchange

This option is very restrictive however. It would allow anyone to buy the coins, and I don't necessarily want them to be bought but given away for free to specific users.

QUESTIONS

  • Are there other options people are aware of?
  • Which option would be most suitable and cost the least amount of gass?

DIFFERENCES BETWEEN THE LINKED DUPLICATE QUESTION AND THIS ONE:
( How to transfer tokens to bounty participants? )

The questions have noticeable differences

  • The details that are being discussed.
  • I also have 2 specific questions at the end which are not identical to that

while the question linked that is similar asks:

  • What is best practice to send ERC20-compliant tokens to bounty participants?

It doesn't provide the specific criteria for what best would refer to, while I do, and I also ask the other available options to make a comparison with. Even though they have similarities, they are not the same.

Best Answer

The best way

The best way is quite an objective term.

The most cost effective way is definitely to execute them all in one loop (option 1), although there will be a limit to how many addresses you can perform at once (you'll probably need to do 10 batches of 100 addresses each).

Option 2 may indirectly cost you less in gas, but someone still has to pay the gas, and since they will be (presumably) executing one by one, the overall gas cost will be more, but since you won't be paying it, maybe that's better for you?

A slightly better implementation:

function distributeToken(address[] addresses, uint256 _value) onlyOwner {
     uint total = _value * addresses.length;
     require(total/_value == addresses.length); // Overflow check
     require(balances[owner] >= total); // Underflow check
     balances[owner] -= total;
     for (uint i = 0; i < addresses.length; i++) {
         balances[addresses[i]] += _value;
         require(balances[addresses[i]] >= _value); // Overflow check
         Transfer(owner, addresses[i], _value);
     }
}

Gas estimations:

For single calls to a typical transfer() function, it's the same cost per call, which means that for each address you'll be paying 23,500 gas.

However when you perform a bulk update instead, you save the overhead of the invocation cost and just have to pay the cost of the loop and storage etc. After a base cost of 27,947 gas, each address only costs an extra 9,703 gas.

┌─────┬────────────┬─────────────────┐
│  #  │  transfer  │ distributeToken │
├─────┼────────────┼─────────────────┤
│   1 │     23,500 │          37,650 │
│   2 │     47,000 │          47,353 │
│   3 │     70,500 │          57,056 │
│  10 │    235,000 │         124,977 │
│  50 │  1,175,000 │         513,097 │
│ 500 │ 11,750,000 │       4,879,447 │
└─────┴────────────┴─────────────────┘

That means after 2 addresses it's cheaper.

For 8 Mgas (maximum for a single call), you could do around 821 addresses:

27,947 base call gas + 9,703 gas/address * 821 addresses = 7,994,110 gas
Related Topic