3

I am working on a contract that lets player place wagers against one another.

I have a struct which looks like this that holds all the wagers

struct Wager {
        address player1;
        address player2:
        uint amount;
    }
 Wager[] public wagers;

after a wager is set an a winner declared I wanted to remove the wager from this array since it is no longer needed and I have no interest in having a history of wagers. I'm also unsure of the effect of this array growing very large in size if there are lots of continuous wagers being made.

Does anyone know of the proper mechanism for removing elements from an array for a case like this?

Thank help is appreciated! Thank You!

1 Answer 1

7

There is more too this than meets the eye.

First, there is no way to truly delete since the transaction that created the element and the previous states of the chain will forever remain part of immutible history.

Second, although it will help reduce chain bloat by marking the storage as useless (in the present state), the delete operation is in fact unavoidably a write to the state which costs gas to execute.

Third, logically deleting an element doesn't reorganize the list. It merely creates a void in the midst of the list, roughly like [a,b,c, nothing, e,f,g]. This _might) create logical problems in or around the contract.

A reorganization is possible in the case of an unordered list. This is done by moving the last element in the list into the slot to delete and then reducing the length of the array. This only works with "unordered" lists because it relies on shuffling the order of the elements. https://medium.com/@robhitchens/solidity-crud-part-2-ed8d8b4f74ec

You may find that either leaving the elements in place or reorganizing around mappings is actually a better data structure. You can also consider a soft delete which admittedly does nothing to reduce chain bloat.

Have a look over here for a mapped struct with delete pattern. Are there well-solved and simple storage patterns for Solidity?

Hope it helps.

UPDATE:

Thanks, smarx, for jumping in. Now, I'm curious!

Is it wrong to think delete is always a net costly operation?

pragma solidity ^0.4.20;

contract Refunds {

    mapping(uint => bool) public data;

    function setIt() public {
        data[1] = true;
    }

    function deleteIt() public {  // net cost ~ 5000 gas
        delete data[1];
    }
} 
4
  • "...the delete operation is in fact unavoidably a write to the state which costs gas to execute." Yes, but the cost of the write is undoubtedly more than made up for by the gas refund.
    – user19510
    Commented Mar 16, 2018 at 0:47
  • No. It costs more than you get back. ethereum.stackexchange.com/questions/15573/… Commented Mar 16, 2018 at 0:51
  • The wager array would be unordered I believe, so deleting and moving the last element should work. Am I right in understanding the mapped struct with delete just sets a variable to represent that the element is deleted? And also is chain bloating something I should even be concerned with? If the contract scales the wager array could have hundreds of thousands of elements. Thanks!
    – Dan
    Commented Mar 16, 2018 at 3:01
  • 1
    @RobHitchens I'm fairly certain that answer is wrong. Setting a value to zero costs 5,000 gas and gives you a 15,000 gas refund. The gas refund is applied at the end of the transaction and can give you up to half of your consumed gas back. This is how, e.g. gastoken.io works.
    – user19510
    Commented Mar 16, 2018 at 3:20

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.