以太坊学习笔记--智能合约效率问题

以太坊学习笔记day5

storage和memory

https://solidity.readthedocs.io/en/v0.4.21/types.html#data-location

Every complex type, i.e. arrays and structs, has an additional annotation, the “data location”, about whether it is stored in memory or in storage. Depending on the context, there is always a default, but it can be overridden by appending either storage or memory to the type. The default for function parameters (including return parameters) is memory, the default for local variables is storage and the location is forced to storage for state variables (obviously).

每个复杂的类型, 例如: 数组和结构体, 都额外有一个声明,叫做"数据存储位置"来指定存储在内存还是硬盘.到底存储在哪, 默认情况下取决于上下文, 但是可以用`storage`和 `memory`来显示声明.函数的参数和函数的返回值默认都是`memory`, 而局部变量默认是`storage`, 并且状态变量必须是`storage`.

There is also a third data location, calldata, which is a non-modifiable, non-persistent area where function arguments are stored. Function parameters (not return parameters) of external functions are forced to calldata and behave mostly like memory.

第三种`数据存储位置`叫做`calldata`, 它是只读的, 临时的区域, 用来存储函数的参数.外部函数的参数被强制设置为`calldata`,并且看上去和`memory`一样.

Data locations are important because they change how assignments behave: assignments between storage and memory and also to a state variable (even from other state variables) always create an independent copy. Assignments to local storage variables only assign a reference though, and this reference always points to the state variable even if the latter is changed in the meantime. On the other hand, assignments from a memory stored reference type to another memory-stored reference type do not create a copy.

`数据存储位置`很重要, 因为它关系到改变和赋值的操作: `storage`和`memory`之间的赋值都会创建一个独立的copy; `storage`之间的赋值仅仅是引用传递, 所引用的对象后期可能会发生改变. 另一方面, 两个`memory`之间的赋值, 则不会创建新的copy.
Summary
  • Forced data location:

    parameters (not return) of external functions: calldatastate variables: storage

  • Default data location:

    parameters (also return) of functions: memoryall other local variables: storage

  • new出来的数组是 memory

//官方文档
pragma solidity ^0.4.0;

contract C {
    uint[] x; // the data location of x is storage

    // the data location of memoryArray is memory
    function f(uint[] memoryArray) public {
        x = memoryArray; // works, copies the whole array to storage
        var y = x; // works, assigns a pointer, data location of y is storage
        y[7]; // fine, returns the 8th element
        y.length = 2; // fine, modifies x through y
        delete x; // fine, clears the array, also modifies y
        // The following does not work; it would need to create a new temporary /
        // unnamed array in storage, but storage is "statically" allocated:
        // y = memoryArray;
        // This does not work either, since it would "reset" the pointer, but there
        // is no sensible location it could point to.
        // delete y;
        g(x); // calls g, handing over a reference to x
        h(x); // calls h and creates an independent, temporary copy in memory
    }

    function g(uint[] storage storageArray) internal {}
    function h(uint[] memoryArray) public {}
}

测试代码

pragma solidity ^0.4.17;



contract  Test{
    
    uint[] public    array ;
    
    
    modifier initArray() {
        delete array; //清空数组
        array.push(1);
        array.push(2);
        _;
    }
    
    function test1() initArray public{
        uint[] storage pArray = array;  //引用
        pArray[0] = 999;
    }
    
    function  test2() initArray public{
        uint[] memory  newArray = array; //值传递, 相当于将array中的拷贝到一个新的数组中
        newArray[0] = 444;
    }
    
    //-------------------------------------------------------
    function test3() public initArray{
        test4(array);
    }
    
    function test4(uint []  memArray) public{
        array = memArray;
        changeArray(array);
    }
    
    // 参数是storage类型时,函数必须是private或internal类型的
    function changeArray(uint[] storage arrayTest) internal{
        arrayTest[0] = 666;
    }
    //-------------------------------------------------------
    
    
}

智能合约效率问题

 function approveRequest(uint nArrayIndex) public{
        require(nArrayIndex < payRequests.length);
        PayRequest storage request = payRequests[nArrayIndex];
        
        //消耗大量gas
        for(uint i = 0; i < addrPlayers.length; i++){
            if(addrPlayers[i] == msg.sender) {
                break;
            }
            if(i == addrPlayers.length - 1 /* && addrPlayers[i] != msg.sender*/){
                require(false);
            }
        }
        
        //消耗大量gas
        for(i =0; i < request.vctVotedAddr.length; i++){
            if(msg.sender == request.vctVotedAddr[i]){
                require(false);
            }
        }
        
        request.nAgreeCount += 1;
        request.vctVotedAddr.push(msg.sender);
    }

优化后

   function approveRequest(uint nArrayIndex) public{
        require(nArrayIndex < payRequests.length);
        PayRequest storage request = payRequests[nArrayIndex];
       
        require(mapPlayer[msg.sender]);
        require(payRequests[nArrayIndex].mapVote[msg.sender] == false);
        request.nAgreeCount += 1;
        payRequests[nArrayIndex].mapVote[msg.sender] = true;
    }

案例: 众筹

pragma solidity ^0.4.17;


//用智能合约部署智能合约
contract FundingFactory{
    
    address[] public fundings; 
    
    function deploy(string _strProName, uint _nSupportMoney, uint _nGoalMoney) public{
        address funding = new Funding(_strProName, _nSupportMoney , _nGoalMoney, msg.sender);
        fundings.push(funding);
    }
    
}


contract Funding{
    
    bool bSuccessFlag = false;
    address public addrManager;
    string public strProjectName;
    uint public nSupportMoney;
    uint public nEndTime;
    uint public nGoalMoney;
    address []  public addrPlayers;
    mapping(address=>bool)  mapPlayer;  //使用mapping提高效率, 降低gas消耗
    
    
    PayRequest[]   public payRequests;  //付款请求结构体
    
    struct PayRequest{
        string  strDesc;
        uint    nPayment; //out 
        address addrShop;
        bool   bCompleted;
        mapping(address=>bool) mapVote;
        //address[] vctVotedAddr;
        uint  nAgreeCount; 
    }
    
    modifier onelyManager(){
        //require(bSuccessFlag);
        require(msg.sender == addrManager);
        _;
    }
    
    
    function   createRequest(string  _strDesc, uint _nPayment, address _addrShop) public onelyManager{
        PayRequest memory  payRequest =   PayRequest({
            strDesc : _strDesc,
            nPayment : _nPayment,
            addrShop : _addrShop,
            bCompleted : false,
            nAgreeCount : 0
        });
        
        payRequests.push(payRequest);
        
    }
    
    
    function Funding(string _strProName, uint _nSupportMoney, uint _nGoalMoney, address _manager) public{
        addrManager = _manager;//msg.sender;
        strProjectName = _strProName;
        nSupportMoney = _nSupportMoney;
        nGoalMoney = _nGoalMoney;
        nEndTime = now + 4 weeks;
       
    }
    
    function getBalance() view public returns(uint){
        return this.balance;
    }
    
    
    function getPlayersCount()public view returns(uint){
        return addrPlayers.length;
    }
    
    function getPlayers() public view returns(address[]){
        return addrPlayers;
    }
    
    function getRemainSeconds() public view returns(uint){
        return (nEndTime - now) ; //seconds
    }
    
    
    function checkStatus() view public{
        require(bSuccessFlag == false);
        require(now > nEndTime);
        require(this.balance > nGoalMoney);
    }
    
    function support() payable public{
        require(msg.value >= 50 wei);
        nSupportMoney += msg.value;
        addrPlayers.push(msg.sender);
        mapPlayer[msg.sender] = true;
    }
    
    function approveRequest(uint nArrayIndex) public{
        require(nArrayIndex < payRequests.length);
        PayRequest storage request = payRequests[nArrayIndex];
       
        require(mapPlayer[msg.sender]);
        require(payRequests[nArrayIndex].mapVote[msg.sender] == false);
        request.nAgreeCount += 1;
        payRequests[nArrayIndex].mapVote[msg.sender] = true;
    }
    
    
    
    // function approveRequest(uint nArrayIndex) public{
    //     require(nArrayIndex < payRequests.length);
    //     PayRequest storage request = payRequests[nArrayIndex];
        
    //     for(uint i = 0; i < addrPlayers.length; i++){
    //         if(addrPlayers[i] == msg.sender) {
    //             break;
    //         }
    //         if(i == addrPlayers.length - 1 /* && addrPlayers[i] != msg.sender*/){
    //             require(false);
    //         }
    //     }
        
        
    //     for(i =0; i < request.vctVotedAddr.length; i++){
    //         if(msg.sender == request.vctVotedAddr[i]){
    //             require(false);
    //         }
    //     }
        
    //     request.nAgreeCount += 1;
    //     request.vctVotedAddr.push(msg.sender);
    // }
    
    
    
    function finilizeRequest(uint nRequestIndex) public{
        PayRequest storage requst = payRequests[nRequestIndex];
        require(requst.bCompleted == false);
        require(requst.nAgreeCount * 2 > addrPlayers.length);
        
        
        //付款
        require(this.balance > requst.nPayment);
        requst.addrShop.transfer(requst.nPayment);
        requst.bCompleted = true;
    }
    
    
    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/783154.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024平价蓝牙耳机哪个牌子好?盘点热门平价蓝牙耳机推荐

2024年来&#xff0c;蓝牙耳机市场逐渐走向平价&#xff0c;这使得越来越多的消费者能够轻松拥有一副高性价比的蓝牙耳机。然而&#xff0c;在如此丰富的选择中&#xff0c;2024平价蓝牙耳机哪个牌子好&#xff1f;成为了许多人的烦恼。为了帮助大家更好地了解市场上的热门产品…

8、开发与大模型对话的独立语音设备

一、设计原理 该系统的核心部分主要由ESP32-WROVER开发板和ESP32-CAM摄像头、MAX9814麦克风放大器模块、MAX98357功放、声音传感器和SU-03T语音识别芯片构成。通过使用ESP32-WROVER开发板,用户可以实现通过语音与ai进行交互并进行人脸识别。 系统中,从外部输入电源中获取电源…

HTML5使用<output>标签:显示一些计算结果

HTML5 提供的 output 标签&#xff0c;用于显示出一些计算的结果或者脚本的其他结果。output 标签必须从属于某个表单&#xff0c;也就是说&#xff0c;必须将 output 标签写在表单内部&#xff0c;或者在该元素中添加 form 属性。 output 标签语法&#xff1a; <output f…

盘点2024年10款超级好用的项目管理软件,建议收藏!

今天猴哥整理并分享国内外使用最广泛的10大项目管理工具软件&#xff0c;同时探讨如何选择适合自己的项目管理工具所需考虑的要素。在国内外市场上&#xff0c;有非常多的项目管理软件可供选择。然而&#xff0c;逐一尝试这些软件将耗费大量时间&#xff0c;因此需要寻找更好更…

vue3中使用 tilwindcss报错 Unknown at rule @tailwindcss

解决方法&#xff1a; vscode中安装插件 Tailwind CSS IntelliSense 在项目中的 .vscode中 settings.json添加 "files.associations": {"*.css": "tailwindcss"}

基于CentOS Stream 9平台搭建MinIO以及开机自启

1. 官网 https://min.io/download?licenseagpl&platformlinux 1.1 下载二进制包 指定目录下载 cd /opt/coisini/ wget https://dl.min.io/server/minio/release/linux-amd64/minio1.2 文件赋权 chmod x /opt/coisini/minio1.3 创建Minio存储数据目录&#xff1a; mkdi…

我是售前工程师转大模型了,不装了我摊牌了

有无售前工程师的朋友&#xff0c;心里的苦谁懂呀&#xff0c;售前工程师是项目开发人员与业务销售人员的桥梁&#xff0c;在业务销售人员眼中&#xff0c;他们是技术人员&#xff0c;在项目实施中的开发人员眼中&#xff0c;他们是专注技术的销售人员&#xff0c;在用户眼中&a…

vue3关于在线考试 实现监考功能 推流拉流

vue3 关于在线考试 实现监考功能&#xff0c; pc端考试 本质是直播推流的功能 使用腾讯云直播: 在线文档 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><link rel"icon" href"/f…

linux 安装Openjdk1.8

一、在线安装 1、更新软件包 sudo apt-get update 2、安装openjdk sudo apt-get install openjdk-8-jdk 3、配置openjdk1.8 openjdk默认会安装在/usr/lib/jvm/java-8-openjdk-amd64 vim ~/.bashrc export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export JRE_HOME${J…

数据分析入门指南Excel篇:各类Excel函数概览与详解(二)

在当今数字化时代&#xff0c;数据已成为推动业务决策和创新的关键因素。而表格结构数据&#xff0c;作为最常见的数据存储形式之一&#xff0c;广泛应用于财务、物流、电商等多个领域。本文将基于提供的材料文本&#xff0c;深入探讨表格数据的处理与分析&#xff0c;特别是通…

【云原生】Kubernetes部署EFK日志分析系统

Kubernetes部署EFK日志分析系统 文章目录 Kubernetes部署EFK日志分析系统一、前置知识点1.1、k8s集群应该采集哪些日志&#xff1f;1.2、k8s比较流行的日志收集解决方案1.3、fluentd、filebeta、logstash对比分析1.3.1、Logstash1.3.2、Filebeat1.3.3、fluentd 1.4、EFK工作原理…

STM32自己从零开始实操08:STM32主控原理图

由于老师使用的各引脚分门别类的单片机原理图我没有找到&#xff0c;我使用是引脚按顺序摆放的&#xff0c;不方便一个模块一个模块截图展示&#xff0c;所以这部分使用老师的原理图。 一、电源 1.1电源的介绍 1.1.1数字电源和地&#xff08;VDD和VSS&#xff09; 数字电源…

修改CentOS7.9跟Unbantu24的ip地址

修改CentOS的IP地址 ip addr 查看IP地址 cd /etc/sysconfig/network-scripts ls vi ifcfg-ens33修改ip地址跟干网关地址 TYPE"Ethernet" PROXY_METHOD"none" BROWSER_ONLY"no" BOOTPROTO"static" DEFROUTE"yes" IPV4_FA…

项目2:API Hunter 细节回顾 -2

一. 接口上线/下线功能 接口的上线和下线是由管理员负责进行的。 上线接口&#xff0c;即发布接口。首先需要判断接口是否存在&#xff0c;然后判断接口是否可调用。如果可以调用&#xff0c;就修改数据库中该接口的状态字段为 1&#xff0c;代表发布&#xff0c;默认状态为 …

精美个人博客 付费搭建

博客演示地址&#xff1a;http://gavana.top/ 1、前端博客页 2、后端管理页 此项目原作者已开源&#xff0c;地址&#xff1a;Naccl/NBlog: &#x1f353; Spring Boot Vue 前后端分离博客系统 https://naccl.top (github.com) 可以自己搭建&#xff0c;我只是负责搭建起可直…

【Java13】包

“包”这个机制&#xff0c;类似于分组。主要作用是区分不同组内的同名类。例如&#xff0c;高三三班有一个“王五”&#xff0c;高二八班也有一个“王五”。高三三班和高三八班就是两个不同的包。 Java中的包&#xff08;package&#xff09;机制主要提供了类的多层命名空间&…

被全球数千企业应用的TOGAF®标准,不仅仅是IT框架

2022 年 4 月 25 日&#xff0c;The Open Group 发布了 TOGAF标准第10版。这不仅仅是 The Open Group 的重要里程碑&#xff0c;也是整个企业架构行业和所有从业者的重大利好。作为企业架构师的首选标准&#xff0c;TOGAF一直以来都受到人们的欢迎。对此&#xff0c;第10版必须…

Java异常详解及自定义异常

认识异常&#xff0c;掌握异常处理主要的5个关键字&#xff1a;throw、try、catch、final、throws并掌握自定义异常 目录 1、异常概念与体系结构 1、1异常的概念 1、2异常体系结构 1、3异常的分类 编译时异常&#xff1a; 运行时异常 &#xff1a; 2、异常处理 2、1防御式…

每日直播分享车载知识:硬件在环、UDS诊断、OTA升级、TBOX测试、CANoe、ECU刷写、CAN一致性测试:物理层、数据链路层等

每日直播时间&#xff1a;&#xff08;进腾讯会议方式&#xff1a;QazWsxEdc_2010&#xff09; 周一到周五&#xff1a;20&#xff1a;00-23&#xff1a;00&#xff08;讲一个小时&#xff0c;实操两个小时&#xff09; 周六与周日&#xff1a;9&#xff1a;00-17&#xff1a;0…

C# 中的Semaphore(信号量)详解与应用

文章目录 1. 信号量是什么&#xff1f;2. C# 中的 Semaphore 类3. 信号量的使用示例3.1 创建信号量3.2使用信号量同步线程 4. 总结 在并发编程中&#xff0c;同步是一种基本的需求。信号量&#xff08;Semaphore&#xff09;是一种常见的同步机制&#xff0c;它用于控制对共享资…