当前位置:首页 » 《随便一记》 » 正文

区块链知识系列 - 系统学习EVM(二)-存储与安全

8 人参与  2023年02月23日 16:03  分类 : 《随便一记》  评论

点击全文阅读


区块链知识系列 - 系统学习EVM(一)

特点

EVM出于所谓运算速度和效率方面考虑,采用了非主流的256bit整数。不支持浮点数缺乏标准库支持,例如字符串拼接、切割、查找等等都需要开发者自己实现给合约打补丁或是部分升级合约代码在EVM中是完全不可能的

存储

image-20221125135742652

Code

code 部署合约时储存 data 字段也就是合约内容的空间,即专门存储智能合约的二进制源码的空间

Storage

Storage 是一个可以读写修改的持久存储的空间,也是每个合约持久化存储数据的地方。Storage 是一个巨大的 map,一共 2 256 2^{256} 2256 个插槽 (slot),每个插糟有 32 bytes,合约中的“状态变量”会根据其具体类型分别保存到这些插槽中。

Stack

stack 即所谓的“运行栈",用来保存 EVM 指令的输入和输出数据。可以免费使用,没有 gas 消耗,用来保存函数的局部变量,数量被限制在 16 个。stack 的最大深度为 1024 ,其中每个单元是 32 byte。

Args

args 也叫 calldata,是一段只读的可寻址的保存函数调用参数的空间,与栈不同的地方的是,如果要使用 calldata 里面的数据,必须手动指定偏移量和读取的字节数。

Memory

Memory 一个简单的字节数组,主要是在运行期间存储数据,将参数传递给内部函数。基于 32 byte 进行寻址和扩展。

安全

溢出攻击

EVM 的 safeMath 库不是默认使用,例如开发者对 solidity 的 uint256 做计算的时候,如果最终结果大于 uint256 的最大值,就会产生溢出变为一个很小的数,这样就产生了溢出漏洞。诸如 BEC、SMT 等相关币种都遭受过溢出攻击,带来了极度严重都后果
对策: 利用一些第三方的safemath库来保证这个数字操作的安全

重入攻击

solidity 一大特性是可以调用外部其他合约,但在将 eth 发送给外部地址或者调用外部合约的时候, 需要合约提交外部调用。如果外部地址是恶意合约,攻击者可以在 Fallback 函数中加入恶意代码,当发生转账的时候,就会调用 Fallback 函数执行恶意代码,恶意代码会执行调用合约的有漏洞函数,导致转账重新提交。最严重的重入攻击发生在以太坊早期,即知名的 DAO 漏洞 - (先转账再扣钱,结果转账到一个恶意合约地址)。
对策: 在金额转移之前,一定要先扣钱

非预期函数执行

EVM 没有严格检查函数调用,如果合约地址作为传入参数可控,可能导致非预期行为发生。

权限问题,如果构造函数(0.4.20之前的版本)名和合约名写的不一致,就会被外部或者其他合约所调用,恶意的攻击者可能获取了我们当前智能合约的所有权
对策: 注意编码规范,保证合约名与构造函数名相同。如果现在使用构造函数,我们建议使用constractor来创建

时间戳依赖

时间戳就可以被矿工修改的

可预测的随机数

使用区块变量生成随机数,所有的区块变量都可以被矿工操纵.因为这些区块变量在同一区块上是共用的。攻击者通过其恶意合约调用受害者合约,那么此交易打包在同一区块中,其区块变量是一样的。

对策: 通过Oracle获取随机数

服务攻击

withdraw时,不要直接把币转到用户指定的某个地址(可能是个恶意合约), 而是让用户主动提取自己的押金

不要空投,而是让人主动来领取.

私有数据

不要以为声明为private的变量外部就无法访问到

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.0 <0.9.0;contract DCA {    uint counter;    uint private age;    constructor(uint _c) {        counter = _c;        age = _c + 2;    }}

通过api可直接按内存地址访问到private的数据

import web3url = ""w3 = web3.Web3(web3.HTTPProvider(url))w3.eth.get_storage_at(address, 0x0)#一个uint占256bit, 即32字节 #HexBytes('0x0000000000000000000000000000000000000000000000000000000000000005')w3.eth.get_storage_at(address, 0x1)# HexBytes('0x0000000000000000000000000000000000000000000000000000000000000007')

注意

tx.origin和msg.sender区别

msg.sender (address): 消息发送方 (当前调用)

tx.origin(address): 交易发送方(完整调用链上的原始发送方)

用户A -> 合约1 -> 合约2

若在合约2中使用 msg.sender,会得到合约1的地址

若在合约2中使用 tx.origin,会得到用户A,即整个调用链的起点

合约间的调用方式call、delegatecall

调用方式修改storage调用者的msg.sender被调用者的msg.sender执行上下文件
call修改被调用者的合约storage交易的发起者地址调用者地址在被调用者里
delegatecall修改调用者的合约storage交易的发起者地址调用者地址在调用者里

receive 和 fallback 调用流程

接收以太功能函数

solidity 接收函数 receive 没有参数、没有返回值。

solidity 向合约转账,发送 Eth,就会执行 receive 函数。

如果没有定义接收函数 receive,就会执行 fallback 函数。

fallback函数,即 回退函数,没有名字,没有参数,没有返回值

function(){}

往期精彩回顾: 区块链知识系列 密码学系列 零知识证明系列 共识系列 公链调研系列 BTC系列 以太坊系列 EOS系列 Filecoin系列 联盟链系列 Fabric系列 智能合约系列 Token系列

点击全文阅读


本文链接:http://www.zhangshiyu.com/post/53346.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 无弹窗全文(许轻衣陆庭深)冷战两年,她离婚他发疯全文畅享阅读
  • 完结文爱如溺海恨意难休结局+番外免费列表_完结文爱如溺海恨意难休结局+番外免费(司漾许澄意柳眠眠)
  • 三国之召唤妖孽系统大反击_刘协精选作品_小说后续在线阅读_无删减免费完结_
  • 我盼孤身纵马,四海任我游在线阅读_蔺昭魏迟连蔺昭更新_小说后续在线阅读_无删减免费完结_
  • 终章小说姜挽宁段秉谦:结局+番外(愿负光阴也负你)已更新+延伸(愿负光阴也负你)清爽版
  • 奉命吃瓜后,我的瓜田遍布全世界是什么小说(云似初叶见深)(奉命吃瓜后,我的瓜田遍布全世界)全本完整清爽版在线+无广告结局
  • (姜挽宁段秉谦)姜挽宁段秉谦小说(愿负光阴也负你)小说全集速览无广告高口碑小说
  • 重生到末日高温前,被污蔑成荡妇的我自请下堂后续+完结_陈风婆婆林溪超长版_小说后续在线阅读_无删减免费完结_
  • 人家拿命下副本,你却用假身逃课?无错版_陈林连载_小说后续在线阅读_无删减免费完结_
  • 完结文犹若清风梦了云宝藏列表_完结文犹若清风梦了云宝藏(晏临渊叶知薇)
  • 儿子来自六年后:结局+番外免费品鉴:结局+番外评价五颗星
  • 完结文开挂辅助成团宠,全星际争当大冤种!结局+番外高口碑列表_完结文开挂辅助成团宠,全星际争当大冤种!结局+番外高口碑(白希薇)

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1