2

I have a timeout on a contract that locks down an account for a certain amount of time.

If transactions happen frequently, and lockouts happen infrequently, would it be cheaper to attempt delete obsolete lockouts every transaction, or just leave them in there.

for example - freeing mem whenever we realize lockout is passed

function transfer(...) {
    require(timeout[msg.sender] < now);  // Is this cheaper if less items in timeout mapping?
    ...
    delete timeout[msg.sender];  // Will this cost ETH if no timeout exists?
}
  • An interesting question. Never thought about that. Using sstore to set something to zero will only cost 5000 gas, instead of 20.000. But what happens if you try sstore zero on a slot which is already zero. I would guess it will still cost 5000 gas. If so, skipping deletes would be cheaper(?) – ivicaa Mar 3 '18 at 17:36
2

I've tested the behaviour with this simple contract:

contract X {
    mapping (address => uint) l;

    function lock() {
        l[msg.sender] = now;
    }

    function unlock() {
        delete l[msg.sender];
    }

    function unlock2() {
        if(l[msg.sender] > 0)
            delete l[msg.sender];
    }
}

Result: zeroing of a slot already containing zeros will still cost you 5000 gas and you'll not get 15000 refund. Hence, it's better to wrap the delete into an if.

Variant 1: always call delete

  1. lock -> 41526 gas
  2. unlock -> 13239 gas (15000 gas refund due to zeroing a non-zero slot)
  3. unlock -> 26477 gas (zeroing a zero slot, costs 5000, but no refund!?)

Variant 2: delete wrapped in if

  1. lock -> 41526 gas
  2. unlock2 -> 13400 gas (15000 gas refund again)
  3. unlock2 -> 21719 gas (delete skipped, overhead for the if)
  • excellent answer! Wish I could upvote twice for the addition of actual costs. Also, stupid related question - how did you get the costs of these things? I haven't found a field in web3 to return actual gas costs yet. – FrozenKiwi Mar 4 '18 at 11:52
  • also any idea why the first unlock2 was actually cheaper than the first unlock1? I would have assumed the addition of the 'if' statement would end up costing extra gas, so unlock2 would be more expensive if lock existed. – FrozenKiwi Mar 4 '18 at 11:55
  • Oops - I got the numbers backwards! - the cost of checking the "if" is 141 gas, cost of delete is 5000. So if we were deleting 35 out of 36 times, it would be cheaper to not check! Thats the numbers I need! Thanks again – FrozenKiwi Mar 4 '18 at 12:32
  • In your case if will cost less, since you'll have the storage lookup, e.g. l[msg.sender] before if. If you store it into a local variable, your if will cost significantly less. Btw. you can see the gas usage in the transaction receipt or in remix GUI when you expand "Details". – ivicaa Mar 4 '18 at 13:12
1

Delete changes the value to zero. This is a state change so yes it will cost gas even if it is already zero.

You want to wrap it in an if so the execution cost is only 400 gas if it doesn't change the state.

pragma solidity ^0.4.0;

contract number {
    uint public num = 0; 

    function setNum(uint _num) public {
        num = _num;
        /*
        * called with _num = 0
        * tx cost :26622 gas
        * execution cost: 5222 gas
        */
    }

    function setNumCheck(uint _num) public {
        if (num != _num) {
          num = _num;
        }
        /*
        * called with _num = 0
        * Tx cost : 21793 gas
        * execution cost: 393 gas
        */
    }

}

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.