I am writing a ICO contract in which if iCO is unsuccessful then ether should get refund from owner of contract to each individual user who has contributed in buying token

mapping (address=>uint256) public totalTokenOwnedByUser;
address[] public tokenOwnedUser;
function transferEtherBackToUser() payable public onlyOwner {
        uint arrayLength = tokenOwnedUser.length;
        for(uint i = 0; i < arrayLength; i++) {
            totalValue += totalTokenOwnedByUser[tokenOwnedUser[i]];
            tokenAddress = tokenOwnedUser[i];

  • What is the question? – Daniel Luca CleanUnicorn Mar 28 '18 at 9:36
  • I am writing a ICO contract in which if iCO is unsuccessful then ether should get refund from owner of contract to each individual user who has contributed in buying token – Ayush Mittal Mar 28 '18 at 9:38
  • Please edit your question and add the background and question – Daniel Luca CleanUnicorn Mar 28 '18 at 9:54

The function will do that for you. But this will be very poor smart contract design with high chances of failure.

Let me explain this to you.

Problem 1

What if one of the users have sent you ethers from a smart contract that don't implement the payable function (i.e his smart contract doesn't accept ethers).

Since you are iterating over an array to transfer funds. When you try to refund that malicious user, the transfer call fails:


and this line reverts all the state change and hence the genuine users also don't get their ETH.

Problem 2:

Now let's assume you don't have any malicious users but you have around 10K users (or more). The gas for this transaction will exceed block gas limit and eventually, your transaction will always fail.

Solution: There is always a solution to every problem.

Always favor pull over push in fund transfers.

This means to allow users to withdraw (pull) their eth instead of pushing eth to their wallet. In this case, only the call of malicious users will fail and won't hamper your genuine users.

Secondly. when users withdraw their eth hence they pay for the gas. Thus there are no chances of exceeding block gas limit.

| improve this answer | |
  • 1
    Very detailed and insightful ! +1'd – Leon Mar 28 '18 at 10:55

The function seems to do this, but you might also need to use the Ethereum to token multiplier.

If for example you receive 100 tokens for each ether you would need to add this in your transfer function

tokenMultiplier = 100 // User gets 100 tokens for each Ether

tokenOwnedUser[i].transfer(totalTokenOwnedByUser[tokenOwnedUser[i]] / tokenMultiplier);

Also you might want to change the function name to transferEtherBackToUsers() to reflect that you are sending the Ether back to the users.

Also you have to test your function and how much gas it costs. There might be a big number of contributors and the loop might now have enough gas to send the Ether back to all of them. It's not only about how much gas you add to the transaction that triggers the refund, but it could be a problem of block gas limit. Even if you would add enough gas to the transaction the block gas limit might be too low.

You could consider splitting the refund into multiple parts (sending to x contributors at a time and make sure to skip the refunded ones at each call) or create a method that each contributor will call to withdraw his own funds.

| improve this answer | |

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.