关灯

Gas usage higher when using the delete keyword

  [复制链接]
区块链技术 发表于 2018-12-18 13:25:48 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x

I'm currently working on a marketplace demo for the consensys bootcamp, you can find my entire code here.

Stores inside the marketplace (which are structs) are stored inside a mapping and the keys pointing to the stores are stored in an array. I have a function that removes a store and I wanted to test gas usage.

I have 2 different approaches:

  • the first one just deletes the item id array and sets a bool flag to false
  • the second approach just uses the delete keyword to delete the struct

.

/// @notice removes an existing store
/// @dev only callable by store owners, requires store to be active
/// @param _storeID ID of store to be removed
/// @return true on success, false on failure
function removeStore(bytes32 _storeID) public onlyStoreOwner returns(bool) {
    // storage pointers to store and store id list
    Store storage store = stores[msg.sender][_storeID];
    bytes32[] storage storeIdList = storeIdLists[msg.sender];

    // store has to be active in order to be removed
    require(store.active, "store currently not active");

    // copy last index of store id list to index of to be removed store and delete last item of array
    storeIdList[store.index] = storeIdList[storeIdList.length-1];
    storeIdList.length--;
    // remove items from store
    store.itemIdList.length = 0;
    store.active = false;

    emit RemovedStore(msg.sender, _storeID);
    return true;
}

function removeStore2(bytes32 _storeID) public onlyStoreOwner returns(bool) {
    // storage pointers to store and store id list
    Store storage store = stores[msg.sender][_storeID];
    bytes32[] storage storeIdList = storeIdLists[msg.sender];

    // store has to be active in order to be removed
    require(store.active, "store currently not active");

    // copy last index of store id list to index of to be removed store and delete last item of array
    storeIdList[store.index] = storeIdList[storeIdList.length-1];
    storeIdList.length--;
    // remove items from store
    delete stores[msg.sender][_storeID];

    emit RemovedStore(msg.sender, _storeID);
    return true;
}

when I test the gas usage of both functions I generate a new store with the name "test" and the description "test". The item id list is empty and the bool flag gets set to true.

the removeStore function has a transaction cost of 26641 gas

as expected, the bool flag is set to false, everything else stays.

now the removeStore2 function has a transaction cost of 37230 gas

again, everything gets deleted as expected

Now to my question:

why does the second function consume more gas? the delete keyword sets 2 more non-zero storages to zero. shouldn't there be a gas refund? The transactions were tested with ganache-cli and the remix javascript vm.




上一篇:Is it ok to store tokens at 0x0?
下一篇:Converting tokens with different decimal places
版权申明:此文如未标注转载均为本站原创,自由转载请注明 本贴地址:https://xuesq.cn/thread-106332-1-1.html 上篇帖子: Is it ok to store tokens at 0x0? 下篇帖子: 动态 | 霍尼韦尔新电子商务平台采用区块链技术 higher when delete keyword
回复

使用道具 举报

 

精彩评论1

正序浏览
区块链技术 发表于 2018-12-18 13:26:15 | 显示全部楼层
 

tl;dr Once you've passed the point where the gas refunds exceed half the total gas used, doing more deletion actually costs more.

If you build a minimal repro of the issue, you get to something like this:

pragma solidity 0.5.1;

contract Test {
    uint256 a = 1;
    uint256 b = 1;

    // gas cost ~= 13000
    function deleteOne() external {
        a = 0;
    }

    // gas cost ~= 15500    
    function deleteBoth() external {
        a = 0;
        b = 0;
    }

    function reset() external {
        a = 1;
        b = 1;
    }
}

(When testing the two functions, be sure to reset() in between.)

This seems surprising at first because we mostly think of deleting (zeroing out storage) as having a negative gas cost, but it actually doesn't. Changing a value in storage from a non-zero value to a zero value has two effects on gas:

  1. It costs 5,000 gas.
  2. It adds 15,000 to the refund counter.

At the end of the transaction, the refund counter is used to subtract up to half of the gas fees.

So in the case of deleteOne:

  • Base transaction fee is 21,000.
  • Writing a zero to storage costs 5,000 gas.
  • Changing a non-zero to a zero adds 15,000 to the refund counter.
  • Total gas fees: 21,000+5,000 = 26,000.
  • After refund: 26000 - min(26000/2, 15000) = 13000

In the case of deleteBoth:

  • Base transaction fee is 21,000.
  • Writing two zeros to storage costs 5,000*2=10,000 gas.
  • Changing two non-zeros to zeros adds 15,000*2=30,000 to the refund counter.
  • Total gas fees: 21,000+10,000 = 31,000.
  • After refund: 31000 - min(31000/2, 30000) = 15500
回复

使用道具 举报

 
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

排行榜

关注我们:微信订阅号

官方微信

APP下载

全国服务邮箱:

admin@xuesq.cn

公司地址:重庆南岸区学府大道

运营中心:重庆微生派网络工作室

邮编:610066 Email:1401171837#qq.com

Copyright   ©2017-2018  中比特Powered by©xuesq.cn!技术支持:中比特    ( 蜀ICP备16009247号-1 )