0

I am trying to understand how gas refunds work. I made this toy contract that fills in an array and separately does some work (loop a ton of times) and then deletes from the array to save on gas. See at the bottom for this contract. Anyway, if I fill a uint8 array by calling input_array() it costs 353965 gas, whereas with a uint256 array it costs 1057665 gas.

But now if I try to get a gas refund with the uint8 array, it does not appear to work as expected. If I run do_work(false, 1000, 0) (no array deletion) it costs 98135 gas. Once the array is filled, if I run do_work(true, 1000, 5) (delete 5 elements from the array), in the uint8 case, it appears I do not get a gas refund and it costs 132211 gas, where as in the uint256 case it costs significantly less at 65336 gas.

Now I supposed it does make sense you should not get as much of a refund by deleting elements from a uint8 array as a uint256 array, but typically when people talk about gas refunds they say you get 10000 gas net refund from deleting an array element.

pragma solidity ^0.4.0;

contract work_and_array {
    uint8[1000] my_array;

    uint last_index = 0;


    function do_work(bool _delete_array, uint32 num_work, uint32 num_delete) public {
        uint256 x = 0;

        for(uint i=0; i<num_work; i++){
            x = x+1;
        }
        if(_delete_array){
            if(last_index >= num_delete) {
                for(uint j = last_index-num_delete; j<last_index;j++){
                    delete my_array[j];
                }
            }
            last_index = last_index-num_delete;
        }
    }

    function delete_array(uint32 num_delete) external {

    }

    function get_length() external returns(uint256){
        return last_index;
    }

    function input_array() external{

        for(uint i=last_index; i<last_index+50; i++) {
            my_array[i]=1;
        }
        last_index = last_index + 50;
    }

}
1

Each write operation costs gas. If it expands storage, it costs more gas. Completely clearing a storage slot refunds gas. The refund relates to storage slots, not array elements.

Storage slots are 32-byte, so a uint256 fills a whole slot, whereas a uint8 only fills part of a slot. This means that your adding case is cheaper with uint8s, because most of the writes overwrite existing storage to cram more stuff in an existing slot, rather than expanding storage.

When you delete, absent optimizations, you have the same number of writes either way, but in the uint8 case most of them are updating the value in the slot, rather than clearing it. You only clear a slot when you remove the last uint8 in it. So you get higher refunds when clearing the uint256s.

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.