Solidity中的calldata,storage,memory

这篇具有很好参考价值的文章主要介绍了Solidity中的calldata,storage,memory。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

calldata

memory

storage

三者之间的转换

storage作为参数,赋值到memory

(1)

(2)

(3)

storage作为参数,赋值给storage

memory作为参数,赋值给memory

memory作为参数,赋值给storage


calldata

官方文档对calldata的描述:

Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory.

翻译:Calldata是一个不可修改的、非持久化的区域,函数参数存储在这里,其行为主要类似于内存。

  • 它只能用于函数声明参数(而不是函数逻辑)

  • 它是不可变的(不能被覆盖和更改),调用数据避免了数据拷贝,并确保数据不被修改

  • 它必须用于external函数的动态参数

  • 它是临时的(该值在事务完成后会销毁)

  • 它是最便宜的存储位置,一般建议将函数参数声明为calldata,因为gas费会比较低。

  • 是const

  • 外部函数的参数(不包括返回参数)被强制指定为calldata

memory

简介:在合约中的本地内存变量。它的生命周期很短,当函数执行结束后就销毁了

  • 内存是一个字节数组,内存槽为256位(32字节)
  • 数据仅在函数执行期间存在,执行完毕后就被销毁,读或写一个内存槽都会消耗3gas
  • 为了避免矿工的工作量过大,22个操作之后的单操作成本会上涨

storage

简介:在合约中可以被所有函数访问的全局变量。storage是永久的存储,意味着以太坊会把它保存到公链环境里的每一个节点

  • 存储中的数据是永久存在的。存储是一个key/value库- 存储中的数据写入区块链,因此会修改状态,这也是存储使用成本高的原因。
    • 占用一个256位的存储槽需要消耗20000 gas,
    • 修改一个已经使用的存储槽的值,需要消耗5000 gas,当清零一个存储槽时,会返还一定数量的gas,
    • 存储按256位的槽位分配,即使没有完全使用一个槽位,也需要支付其开销

三者之间的转换

storage作为参数,赋值到memory

(1)

pragma solidity ^0.4.24;

contract Person {

    int public _age;

    constructor (int age) public {
      _age = age;
    }

    function f() public view{
      modifyAge(_age);
    }

    function modifyAge(int age) public pure{
      age = 100;
    }
}
  • 分析
    • 在这里一开始deploy合约时,传入的age值为30,此时_age的值为30
    • 然后运行f()函数,在这里使用了为storage类型的_age作为函数modifyAge的参数,相当于创建了一个临时变量age(memory类型),将storage类型的变量_age赋值给memory类型的变量age,是值传递,所以在modifyAge函数中,age变量的值的变化并不会影响到_age变量的值
    • 所以再查看_age的值,还是为30

(2)

pragma solidity ^0.4.24;

contract Person {

    string public  _name;

    constructor() public {
        _name = "chenqin";
    }

    function f() public view{
        modifyName(_name);
    }

    function modifyName(string name) public pure{
        string memory name1 = name;
        bytes(name1)[0] = 'L';
    }
}
  • 分析
    • 在这里一开始deploy合约时,设置的_name为"chenqin"
    • 然后,调用f()函数,将storage类型的状态变量_name作为参数,赋值给函数modifyName函数的memory类型的name,为值传递
    • 之后,在modifyName函数中,还将memory类型的name赋值给memory类型的name1,为引用传递!改变一个另一个也跟着改变,
    • 最后,因为先是进行了值传递,name与_name之间已经互不影响了,所以不会跟着改变_name。(标记)处的代码并不会修改_name的值
    • 因此,不管如何以上函数,_name始终为chenqin

(3)

pragma solidity ^0.4.24;

contract Person {

    string public  _name;
    string public changedName;

    constructor() public {
        _name = "chenqin";
    }

    function f() public{//不能声明为view,因为改变了状态变量
        modifyName(_name);
    }

    function modifyName(string name) public{//不能声明为view,因为改变了状态变量
        changedName = name;
        bytes(name)[0] = 'L';
    }
}
  • 分析
    • 调用f()函数,将storage类型的状态变量_name作为参数,赋值给函数modifyName(string) memory类型的name形参,为值传递
    • 然后,memory类型的name作为形参,赋值给storage类型的状态变量changedName,为值传递
    • 因此,(标记)的那行代码,name的值的改变不会导致changedName的值的改变,更不要说_name了
    • 调用f函数,最终的结果是:_name=chenqin,changeName=chenqin

storage作为参数,赋值给storage

pragma solidity ^0.4.24;

contract Person {

    string public  _name;

    constructor() public {
        _name = "chenqin";
    }

    function f() public{
        modifyName(_name);
    }

    function modifyName(string storage name) internal {
        string storage name1 = name;
        bytes(name1)[0] = 'L';
    }
}

PS:如果modifyName函数不声明为internal会报错:这是因为形参是默认为memory类型的,这里声明为storage,那么函数的类型就必须声明为internal或者private

  • 分析
    • 调用f()函数,首先会将为storage类型的_name变量,赋值给modifyName函数storage类型的name,为引用传递
    • 然后在modifyName函数中,将storage类型的name变量,赋值给storage类型的name1变量,为引用传递
    • 都为引用传递,所以最后name1值的变化会导致_name的值的变化
    • 调用f函数前:_name=chenqin。调用f函数后:_name=Lhenqin

引申:其实在这里如果将modifyName(string)函数改成如下,也是能够成功的,因为其实没必要进行两次引用传递文章来源地址https://www.toymoban.com/news/detail-816469.html

function modifyName(string storage name) internal {
        bytes(name)[0] = 'L';
    }

memory作为参数,赋值给memory

pragma solidity ^0.4.24;

contract Person {

    function modifyName(string name) public pure returns(string){
        string memory name1 = name;
        bytes(name1)[0] = 'L';
        return name;
    }
}
  • 分析
    • 这里调用modifyName函数,将memory类型的name,赋值给memory类型的name1,为引用传递
    • 这时候改变name1的值,它的值也随之改变

memory作为参数,赋值给storage

pragma solidity ^0.4.24;

contract Person {

    string public  _name;

    constructor() public {
        _name = "chenqin";
    }

    function f(string name) public{
        _name = name//(x)
        name = "ikun"(y)
    }

}
  • 分析
    • 调用f函数,将memory类型的name,赋值给storage类型的_name,为值传递
    • (x)处_name的值会被修改成name,然后不再随name的改变而改变,即(y)处代码对_name无影响。
    • f函数执行完的结果还是:_name=chenqin

到了这里,关于Solidity中的calldata,storage,memory的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Solidity内存布局介绍 Layout in Memory and Storage

    Solidity reserves four 32-byte slots, with specific byte ranges (inclusive of endpoints) being used as follows: 0x00 - 0x3f (64 bytes): scratch space(暂存空间) for hashing methods  Hash方法的暂存空间. 0x40 - 0x5f (32 bytes): currently allocated memory size (aka. free memory pointer) 0x60 - 0x7f (32 bytes): zero slot Solidity保留了四个32字节的

    2024年02月16日
    浏览(44)
  • 某60区块链安全之Storage任意地址写实战学习记录

    学会使用python3的web3模块 学会分析以太坊智能合约中的Storage变量存储问题 找到合约漏洞进行分析并形成利用 Ubuntu18.04操作机 python3 EVM 中,有三个地方可以存储变量,分别是 Memory、Stack 和 Storage。Memory 和 Stack 是在执行期间临时生成的存储空间,主要负责运行时的数据存储,

    2024年02月05日
    浏览(36)
  • 【区块链 | Solidity】跟我学 Solidity(7):事件

    如何使用事件记录数据 原文: https://medium.com/better-programming/learn-solidity-events-2801d6a99a92 作者: wissal haji 欢迎订阅《Solidity智能合约零基础开发教程专栏》系列文章。 在今天的文章中,我们将看到如何使用web3.js从区块链中读取事件。 Solidity中的事件就像你习惯于使用其他语

    2024年01月25日
    浏览(52)
  • 区块链2——Solidity智能合约开发

    区块链 索引目录 智能合约是一种以代码形式编写的自动执行合约,它们运行在区块链上。这些合约定义了在特定条件下发生的事件以及相应的行为。 1.1 智能合约结构 版本声明(Version Declaration): 智能合约通常以声明版本开始,指定合约应该使用的Solidity编译器版本。例如

    2024年02月05日
    浏览(65)
  • 区块链智能合约编程语言 Solidity

    上文介绍了区块链生态发展,我们知道以太坊的到来可以使开发人员基于区块链开发DApp,本文介绍 Solidity 编程语言的使用,然后基于 Solidity 编写一个简单的智能合约。 Solidity 是以太坊开发人员使用的编程语言,用来编写智能合约,运行在以太坊虚拟机(EVM)上。 有开发经

    2024年02月12日
    浏览(56)
  • 【区块链Solidity】开发环境的注册与认证

     往期文章 【区块链Solidity】智能合约与Solidity介绍 目录 工具介绍  百度超级链 目前开发智能合约的IDE,首推还是Remix,而Remix官网,总是由于各种各样的(网络原因)无法使用,我们可以在本地搭建智能合约开发环境remix-ide,除此之外我们还可以使用国内的百度超级链进行

    2024年02月08日
    浏览(34)
  • 【区块链 | Solidity】Solidity开发教程:用Web3.js构建第一个Dapp

    Web3.js 使用的实用介绍 原文 作者:wissal haji 欢迎订阅《Solidity智能合约零基础开发教程专栏》系列文章。 如果你一直在跟着这个系列学习,那么你已经掌握了编写自己的智能合约。 因此,今天给大家介绍一下构建去中心化应用的全貌,并向大家介绍一下web3.js,这是构建da

    2024年01月24日
    浏览(50)
  • 【区块链实战】Solidity 智能合约如何给账户充值

    目录 一、实战场景 二、知识点 智能合约 智能合约函数 智能合约充值 payable 智能合约部署地址 智能合约的运行 合约 this 对象 三、菜鸟实战 四、运行结果 Solidity 智能合约如何给账户充值 1、充值金额 2、充值并查看结果

    2024年02月09日
    浏览(46)
  • 【区块链学习最全教程】学习 Solidity,全栈 Web3,Javascript 和区块链开发

    Chainlink 开发者社区发布了一个关于全栈 web3,solidity 和区块链开发的完整视频教程。本视频教程由 Chainlink 开发者大使 Patrick Collins 讲解。教程由浅入深讲解了区块链的基础知识,智能合约基础以及流行的开发工具。视频内容覆盖广泛,不论是初学者还是资深工程师,都会从中

    2023年04月09日
    浏览(54)
  • 【区块链-智能合约工程师】第二篇:Solidity入门

    参考文章:一文速览2022十大智能合约开发工具 资料地址:WTF学院 HelloWorld remix:在线智能合约开发IDE(Integrated Development Environment,集成开发环境),可以在浏览器中快速部署测试智能合约。 合约HelloWorld: 事项 说明 代码所用的软件许可(license) 不写许可的话编译时会警告

    2024年02月09日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包