0

I'm learning Solidity and following one of the tutorials online. I'm basically making simple crowdsourcing application which can accept donation from the users.

The withdraw function is defined as below. I omitted the withdrawal logic for simplicity. Funders is an array of address which keeps the record of the users who funded to this contract. Once I withdraw the money, I'm resetting the funders array.

function withdraw() payable onlyOwner public {
  ...withdrawal logic...
  funders = new address[](0);
}

When you look at the above code, I'm initializing the fixed size (0) of an array which is a type of address and assigns it to funders. When I initialize fixed-size array of 0, I thought I can't append an object in the array anymore. Turns out, I can.

Can someone help me understand what I misunderstood here?

1
  • It will help if you add to the question how funders is defined? At the contract level or inside the withdraw function.
    – Ismael
    Nov 30, 2021 at 5:19

1 Answer 1

0

You can append new items to storage arrays but not to memory ones. The only way to grow a memory array is to abandon it and allocate a new one using the new operator while with storage ones you can use push() and pop() to add/remove items.

Memory arrays cannot grow because Solidity uses a very simple memory allocation scheme - it always allocates the variable at the first available location past all the already allocated ones. Once allocated, memory variables are never freed.

Storage is different. First of all it's much, much bigger than memory and there's no extra cost associated with writing at arbitrary locations. Solidity uses this fact to simply place your array at a pseudo-random location. It's technically possible that it could overlap with another variable but the probability of that actually happening is vanishingly small. The location is not truly random - it's based on a keccak hash of the address of the slot used to keep the array length. That slot is detached from the array data and allocated serially somewhere close to the beginning of storage address space along with other storage variables.

See my earlier answer about storage and memory layout of strings to see this layout explained on a specific example.

Also note that the array type you're using (address[]) is actually a dynamically-sized one. I.e. it does not have predefined length and you can choose it at runtime, when the array is allocated (e.g. new array[](5)). This is different from statically-sized arrays (e.g. address[5]) which actually have a fixed size known at compilation time and cannot be resized even in storage.

2
  • I really appreciate your lengthy & detailed answer. So is new address[](0) basically creating a dynamic-sized array but with 0s? Nov 29, 2021 at 1:51
  • It's actually allocating a dynamically-sized array of length zero and returning a reference to it. I.e. there are no elements in the array. It occupies exactly 32 bytes and all of it is taken by the length field (set to zero).
    – cameel
    Nov 29, 2021 at 2:00

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.