18

I am writing a smart contract to be the backend of a game. Instead of using a mapping, I have decided to use an array to store the addresses of accounts who have paid my contract. (I know it is common practice to use a mapping for this but I find them to be confusing)

address[] paidPlayers;

As players join, their address is added via the following function.

function addPlayer(address player) constant returns (address[]) {
   paidPlayers.push(player);
   return paidPlayers;
}

Periodically, when a round in the game is completed, I want my contract to reset. I thus need a way of emptying my paidPlayers array. How is this done in solidity? Is there anything like the javascript

paidPlayers = [];

I have found methods for deleting a specific element but not the array as a whole.

Bryan Campbell
  • 421
  • 2
  • 5
  • 10

4 Answers4

36

From Solidity Documentation Tips and Tricks

Use delete on arrays to delete all its elements.

delete paidPlayers;

This is exactly the same as paidPlayers.length = 0

Ismael
  • 30,570
  • 21
  • 53
  • 96
  • 1
    Caveat! if the array is too large it will cause a run out of gas error!

    An alternative is to use mappings of uint256 and a totalNumberOfElements to handle where to save the values. In case of clear/reset you set totalNumberOfElements = 0.

    For inserts, you should use myArray[totalNumberOfElements] = value

    – imazzara Jan 03 '19 at 15:06
  • @imazzara You are correct but there's an important difference deleting an array will reset all the data to zero. In a case of mapping you have to explicitely delete each item, if you do not delete it and reuse an index it will still have the previous data. – Ismael Jan 03 '19 at 15:57
  • 2
    Right, but it depends on how you manage the access to them. I mean, you can let users only to get items with something like getItemAtIndex where you check the bounds with the valid totalNumberOfElements instead of making the mapping public.

    The rule should be: "If you are not confident about the size of the array, you will need to use mappings to prevent a possible DoS."

    Moreover, it saves gas, cause you are re-using the slots instead of empty all of them.

    – imazzara Jan 03 '19 at 16:02
  • 1
    After deleting an array; how much gas refund will be made? would it be 15.000 or the 15.000 * length_of_the_array ? Please see (https://ethereum.stackexchange.com/q/69882/4575) for more detail in question. @Ismael – alper Apr 19 '19 at 19:02
  • This doesn't work for mappings. – Luke Hutchison May 30 '22 at 23:42
  • 1
    @LukeHutchison The question is about arrays not mappings. It is not possible to delete all elements from a mapping because keys aren't stored. – Ismael May 31 '22 at 03:14
  • 1
    @Ismael correct, I know that -- I was just offering some related information. Sorry if you thought it was off-topic. – Luke Hutchison Jun 01 '22 at 04:19
  • Seems delete has not been supported since 0.6 version. There is no info about it in their press release https://blog.soliditylang.org/2019/12/17/solidity-0.6.0-release-announcement/, but it is mentioned in https://docs.soliditylang.org/en/v0.8.11/060-breaking-changes.html?highlight=Pop#explicitness-requirements – Gleichmut Aug 11 '22 at 13:08
6
You can manually set the array length to 0 with:
paidPlayers.length = 0;

This will clear all entries in the array.

Update: starting with Solidity v0.6, the length member is read-only. You can no longer delete an array by setting the length to zero.

Paul Razvan Berg
  • 17,902
  • 6
  • 73
  • 143
AnAllergyToAnalogy
  • 3,553
  • 11
  • 23
2

you can assign the array to a new empty array

   paidPlayers=new address[](0);
Yilmaz
  • 1,580
  • 10
  • 24
  • 1
    Is this more or less gas efficient than just deleting the array using Ismael's solution? – Paul Razvan Berg Oct 03 '22 at 09:31
  • 1
    Update: it turns out assigning to an empty array is less gas efficient than using delete. To see this you can run this code snippet on Remix. The Foo contract's method cost 39,951 gas, while the Bar contract's method cost 40,030 gas. – Paul Razvan Berg Oct 03 '22 at 09:36
0

You can manipulate the array using assembly assuming it's stored in memory...

function _resizeArray(
    address[] memory array,
    uint256 size
) internal pure {
    assembly {
        mstore(array, size)
    }
}

0xCourtney
  • 314
  • 1
  • 9