1

I have a storage dynamic array.

uint[] public x1;

It contains 4 elements (1,2,3,4)

// Costs 22000
function test() {
   assembly {
     sstore(0,0)
   }
}

// costs 37000
function test() {
  delete x1;
}

Ofc, I deploy contract with the 1,2,3,4 before I call each of these functions. How does delete x1 end up having this more ? as I understand, in the docs, it's stated that for dynamic arrays, it changes the length of the array only so from 4 to 0 which should consume 5000 gas - 4800(refund) = 200. but the difference ends up huge (15000). Any idea?

1 Answer 1

0

You array has 4 elements.

In your first function, you just set the slot0 to 0, therefor you deleted just a single storage slot. (Slot zero in this case, contains the number of elements in the dynamic array).

Your second example here is deleting the entire dynamic array, all 4 elements + the slot0. (5 storage slots in total). The cost of deleting 5 slots vs 1 is the gas difference you get.

In short: delete x1 will delete the entire array (including all of its elements)

Bellow is the code you can use in Remix to play around, experiment with to understand better what is going on when using delete vs sstore.

//SPDX-License-Identifier: UNLICENCED

pragma solidity 0.8.3;  

contract ReadArrayStorage {

    uint[] newArray = [1,2,3,4];

     ///////////////// Main Functionality /////////////////////
    function updateArray(uint[] calldata recievedArray)public {
            newArray = recievedArray;
    }

    function readArray() public view returns (uint[] memory) {
        return newArray;

    }

    function deleteNewArray() public {
        delete newArray;
    }


    ///////////////// Assembly Functions for Reading Storage /////////////////////
    function updateSlot(uint256 slotNumber, uint256 newValue) public {

        assembly {
            sstore(slotNumber, newValue)
        }
    }

    function readSlot(uint slotNumber) public view returns (uint value) {
        assembly{
            value := sload(slotNumber)
        }

    }

    // Returns storage Location of the newArray (uint128 => elementSize == 128, uint => elementSize == 256)
    function arrLocation(uint256 slot, uint256 index, uint256 elementSize) public pure returns (uint256) {
        return uint256(keccak256(abi.encodePacked(slot))) + (index * elementSize/256) ;
    }



}

NOTE: I edited the code to make it easier to understand (now using unit instead of uint128)

Just to be even more certain, I did one more test where I added 5 more elements to the array:

uint[] smallArray = [1,2,3,4];

uint[] bigArray = [1,2,3,4,5,6,7,8,9];

// Gas cost = 37000
function deleteSmallArray() public {
    delete smallArray;
}

// Gas cost = 57000
function deleteBigArray() public {
    delete bigArray;
}

The increase in the gas cost is in line of what one would expect if the number of elements was the reason for the gas cost.

2
  • note that documentation says otherwise. but it can also be used on arrays, where it assigns a dynamic array of length zero or a static array of the same length with all elements set to their initial value which means for dynamic, it shouldn't be going through each element and setting 0. Dec 11, 2022 at 15:38
  • I had just tested it myself (And have posted the code you can use to test it). I can always make a mistake like anybody else, so feel free to double-test it.
    – Sky
    Dec 11, 2022 at 15:43

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.