solidity编程中遇到的各种问题--数据结构篇

Posted 一袋芋头

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了solidity编程中遇到的各种问题--数据结构篇相关的知识,希望对你有一定的参考价值。

solidity的数据结构

1.Mapping的删除

情景:在完成合约的一些交易后要将本次使用过的一些mapping数据删除(或重置),以供下次或其他人使用合约的状态变量

注意:
mapping的delete:只是删除对应某个key的value,而不能直接删除整个mapping,所以要想删除该mapping的每一个key时,往往要把每一个key放进一个动态数组,然后遍历该数组进行删除。

问题:如果要删除一个mapping里的另一个mapping,是直接删除外层mapping,还是要把里层mapping的每个Key都删除?

测试:

// SPDX-License-Identifier: SimPL-2.0
pragma solidity ^0.4.18;
	struct result 
	    int[] results;
	    mapping(int => uint) resultcount;
	
	mapping(address => result) CSToResult;
	
	//设置值
	function setresults(int _result, uint _count)public 
	    CSToResult[msg.sender].results.push(_result);
	    CSToResult[msg.sender].resultcount[_result] = _count;
	
	
	//获取results数组和对应某一个result的count
	function getresults(int _result) public view returns(int[],uint)
	    return (CSToResult[msg.sender].results,CSToResult[msg.sender].resultcount[_result]);
	
	/*
	以下将采取三种方式对CSToResult这个mapping进行删除
	1.直接删除CSToResult[msg.sender];
	2.删除CSToResult[msg.sender]中的每一个result的count及results数组;
	3.在2的基础上再删除删除CSToResult[msg.sender];
	*/
	function deleteData1()public 
	
	    delete CSToResult[msg.sender];
	
	
	function deleteData2()public 
	    
	    for(uint i =0; i <CSToResult[msg.sender].results.length;i++)
	        delete CSToResult[msg.sender].resultcount[CSToResult[msg.sender].results[i]];
	    
	    delete CSToResult[msg.sender].results;
	
	
	function deleteData3()public 
	    for(uint i =0; i <CSToResult[msg.sender].results.length;i++)
	        delete CSToResult[msg.sender].resultcount[CSToResult[msg.sender].results[i]];
	    
	    delete CSToResult[msg.sender].results;
	    delete CSToResult[msg.sender];
	

注意:
这里不能把CSToResult设置成public的

我觉得是因为结构体里边含了个动态数组的缘故(之前用过结构体里含一个mapping,也可以设置成public类型,所以应该不是内层mapping的问题)

下面对每一种方法进行测试;
我们分别把1,1;
2,2;
3,3;
3,5 push进去,然后分别用三个函数进行删除,观察删除效果及gas消耗情况

注意:gas cost可以分为Execution cost和transaction cost

Execution cost包括存储全局变量以及方法调用相关的运行环境的开销。同一个函数,每次调用时的execution cost有可能是不同的。(比如全局变量发生了变化导致)

而Transaction cost和编译后的合约代码长度相关,也和execution cost相关。同一个合约,每次执行时transaction cost - execution cost的值应该是不变的。

删除前先查看一下

1.直接删除CSToResult[msg.sender]:调用deleteData1()
gas消耗:

再查看一下

发现,仅仅将大Mapping对应struct里的其他数据结构变为了初值,里层的mapping其实是不受影响的。

2.调用deleteData2()
gas消耗:

再查看一下

这次基本上成功了,但是不知道外层mapping有没有成功删除。

3.调用deleteData3()
gas消耗:

再查看一下

和2的效果是一样的,但是gas明显多了,所以删除外层mapping应该是有用的。

…写到这里我又想到了第四种方法,就是不删除结构体里的动态数组,反正结果是一样的。。稍微测试了一下

	function deleteData4()public 
	    
	    for(uint i =0; i <CSToResult[msg.sender].results.length;i++)
	        delete CSToResult[msg.sender].resultcount[CSToResult[msg.sender].results[i]];
	    
	   // delete CSToResult[msg.sender].results;
	    delete CSToResult[msg.sender];
	

效果一样,gas比方法3稍微少一点,也只比2多了百十wei,…还不错

总结:要想保险一点,要把内层mapping删除,再把外层mapping删除,这样应该是技能达到效果又能省亿点点gas的吧

以上是关于solidity编程中遇到的各种问题--数据结构篇的主要内容,如果未能解决你的问题,请参考以下文章

solidity编写智能合约遇到的各种问题

solidity编写智能合约遇到的各种问题

第84篇 笔记-智能合约(solidity)编程

智能合约语言 Solidity 教程系列6 - 结构体与映射

第127篇 solidity 中链表的实现

详解 Solidity 事件Event - 完全搞懂事件的使用