【区块链安全 | 第二十四篇】单位和全局可用变量(二)

news2025/4/3 6:00:03

文章目录

  • 单位和全局可用变量(Units and Globally Available Variables)
    • 特殊变量和函数
      • 1. 区块和交易属性
      • 2. ABI 编码和解码函数
      • 3. bytes 成员函数
      • 4. string 成员函数
      • 5. 错误处理
      • 6. 数学和加密函数
      • 7. 地址类型成员函数
      • 8. 与合约相关
      • 9. 类型信息

在这里插入图片描述

单位和全局可用变量(Units and Globally Available Variables)

特殊变量和函数

1. 区块和交易属性

在全局命名空间中始终存在一些特殊变量和函数,主要用于提供区块链相关信息或作为通用工具函数。

  • blockhash(uint blockNumber) returns (bytes32):返回指定区块的哈希值,仅适用于最近 256 个区块;否则返回 0。
  • blobhash(uint index) returns (bytes32):返回当前交易中第 index 个 blob 的版本化哈希值。版本化哈希由 1 个字节的版本号(目前为 0x01)和 KZG 承诺的 SHA256 哈希的后 31 个字节组成(EIP-4844)。如果不存在该索引的 blob,则返回 0。
  • block.basefee (uint):当前区块的基础费用(EIP-3198 和 EIP-1559)。
  • block.blobbasefee (uint):当前区块的 blob 基础费用(EIP-7516 和 EIP-4844)。
  • block.chainid (uint):当前链的 Chain ID。
  • block.coinbase (address payable):当前区块矿工的地址。
  • block.difficulty (uint):当前区块的难度(仅适用于 Paris 之前的 EVM 版本)。在其他 EVM 版本中,它是 block.prevrandao 的废弃别名(EIP-4399)。
  • block.gaslimit (uint):当前区块的 gas 限制。
  • block.number (uint):当前区块的编号。
  • block.prevrandao (uint):由信标链提供的随机数(适用于 EVM >= Paris)。
  • block.timestamp (uint):当前区块的时间戳(自 Unix 纪元以来的秒数)。
  • gasleft() returns (uint256):返回当前交易中剩余的 gas。
  • msg.data (bytes calldata):完整的 calldata(调用数据)。
  • msg.sender (address):消息(当前调用)的发送者地址。
  • msg.sig (bytes4):calldata 的前 4 个字节(即函数标识符)。
  • msg.value (uint):随消息发送的 Wei 数量。
  • tx.gasprice (uint):交易的 gas 价格。
  • tx.origin (address):交易的原始发送者地址(完整调用链中的最初发起者)。

注意
1.msg 变量的动态性
msg.sender、msg.value 等 msg 成员的值会在每次外部函数调用时发生变化,包括调用库函数时。

2.区块和交易属性的限制
当合约在链下执行(如本地测试或模拟环境)时,不要假设 block. 和 tx. 具有特定的值,这些值取决于 EVM 实现。

3.不要依赖 block.timestamp 或 blockhash 作为随机数源
block.timestamp 和 blockhash 可能受到矿工的操纵,在某些应用中,恶意矿工可以重复计算直到获得有利的哈希值。当前区块的时间戳必须严格大于上一个区块的时间戳,但唯一的保证是它位于两个连续区块的时间戳之间。

4.blockhash 的可用性
由于可扩展性原因,并非所有区块的哈希值都可用,只有最近 256 个区块的哈希值可访问,超过该范围的值将返回 0。

5.废弃的函数和别名:
block.blockhash 在 Solidity 0.4.22 版本被弃用,并在 0.5.0 版本中移除。
msg.gas 在 Solidity 0.4.21 版本被弃用,并在 0.5.0 版本中移除(替换为 gasleft())。
now(block.timestamp 的别名)在 Solidity 0.7.0 版本中被移除。

2. ABI 编码和解码函数

  • abi.decode(bytes memory encodedData, (…)) returns (…):对给定的 encodedData 进行 ABI 解码,第二个参数括号内指定解码后的数据类型。示例:
    solidity
    (uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes));

  • abi.encode(…) returns (bytes memory):对给定的参数进行 ABI 编码。

  • abi.encodePacked(…) returns (bytes memory):对给定的参数进行紧凑编码(packed encoding)。注意:紧凑编码可能会导致数据歧义!

  • abi.encodeWithSelector(bytes4 selector, …) returns (bytes memory):以 selector 作为前缀,对后续参数进行 ABI 编码。

  • abi.encodeWithSignature(string memory signature, …) returns (bytes memory):等效于:
    solidity
    abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), …)

  • abi.encodeCall(function functionPointer, (…)) returns (bytes memory):对函数指针 functionPointer 及其参数进行 ABI 编码,同时进行完整的类型检查,确保参数类型与函数签名匹配。结果等价于:
    solidity
    abi.encodeWithSelector(functionPointer.selector, (…))

注意
1.这些编码函数可用于构造外部函数调用的数据,而不实际调用该函数。
2.keccak256(abi.encodePacked(a, b)) 可用于计算结构化数据的哈希值。警告:不同的参数类型可能导致哈希碰撞,应谨慎使用。
3.详细的 ABI 编码规则和紧凑编码(tightly packed encoding)请参考 Solidity 文档。

3. bytes 成员函数

bytes.concat(…) returns (bytes memory):将多个 bytesbytes1bytes32 类型的参数连接成一个字节数组。

4. string 成员函数

string.concat(…) returns (string memory):将多个字符串参数连接成一个字符串。

5. 错误处理

  • assert(bool condition):如果条件不成立,会触发 Panic 错误并回滚状态更改 - 用于内部错误。

  • require(bool condition):如果条件不成立,回滚并撤销交易 - 用于输入错误或外部组件错误。

  • require(bool condition, string memory message):如果条件不成立,回滚并撤销交易,并提供错误消息 - 用于输入错误或外部组件错误。

  • revert():中止执行并回滚状态更改。

  • revert(string memory reason):中止执行并回滚状态更改,并提供一个解释字符串。

6. 数学和加密函数

  • addmod(uint x, uint y, uint k) returns (uint) :计算 (x + y) % k,其中加法是以任意精度执行的,不会在 2^256 上溢出。从版本 0.5.0 起,确保 k != 0。

  • mulmod(uint x, uint y, uint k) returns (uint):计算 (x y) % k,其中乘法是以任意精度执行的,不会在 2^256 上溢出。从版本 0.5.0 起,确保 k != 0。

  • keccak256(bytes memory) returns (bytes32):计算输入的 Keccak-256 哈希值。
    之前 keccak256 有一个别名叫 sha3,在版本 0.5.0 中已被移除。

  • sha256(bytes memory) returns (bytes32):计算输入的 SHA-256 哈希值。

  • ripemd160(bytes memory) returns (bytes20):计算输入的 RIPEMD-160 哈希值。

  • ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):从椭圆曲线签名中恢复与公钥相关联的地址,如果发生错误则返回零。该函数参数对应于 ECDSA 签名的值:

    • r = 签名的前 32 字节
    • s = 签名的第二个 32 字节
    • v = 签名的最后 1 字节

    ecrecover 返回一个地址,而不是一个可支付地址。如果需要将资金转移到恢复的地址,可以通过 address payable 进行转换。

    进一步说明
    在使用 ecrecover 时需要注意,一个有效的签名可以被转换成另一个有效的签名,而无需了解对应的私钥。在 Homestead 硬分叉中,针对交易签名的问题(参见 EIP-2)已被修复,但 ecrecover 函数未做更改。通常这不会造成问题,除非你要求签名是唯一的,或者使用签名来识别项目。你可以使用 OpenZeppelin 的 ECDSA 辅助库,它是 ecrecover 的封装,避免了这个问题。

注意
在私有区块链上运行 sha256、ripemd160 或 ecrecover 时,可能会遇到 “Out-of-Gas” 错误。这是因为这些函数作为“预编译合约”实现,只有在接收到第一个消息后才真正存在(尽管它们的合约代码是硬编码的)。发送到不存在的合约的消息更昂贵,因此执行可能会出现 “Out-of-Gas” 错误。解决该问题的方法是,先向每个合约发送 Wei(例如 1),然后再在实际合约中使用它们。这个问题在主网或测试网上并不存在。

7. 地址类型成员函数

1.<address>.balance (uint256) 返回地址的余额,以 Wei 为单位。

2.<address>.code (bytes memory) 返回地址处的代码(可能为空)。

3.<address>.codehash (bytes32) 返回地址的代码哈希。

4.<address payable>.transfer(uint256 amount) 向地址发送指定的 Wei 数量,失败时回滚,转发 2300 gas 补助,不可调节。

5.<address payable>.send(uint256 amount) returns (bool) 向地址发送指定的 Wei 数量,失败时返回 false,转发 2300 gas 补助,不可调节。

6.<address>.call(bytes memory) returns (bool, bytes memory) 进行低级 CALL,带有给定的有效载荷,返回成功状态和返回数据,转发所有可用的 gas,可以调节。

7.<address>.delegatecall(bytes memory) returns (bool, bytes memory) 进行低级 DELEGATECALL,带有给定的有效载荷,返回成功状态和返回数据,转发所有可用的 gas,可以调节。

8.<address>.staticcall(bytes memory) returns (bool, bytes memory) 进行低级 STATICCALL,带有给定的有效载荷,返回成功状态和返回数据,转发所有可用的 gas,可以调节。

警告
1.尽量避免使用 .call(),因为它绕过了类型检查、函数存在性检查和参数打包。
2.使用 send 时有一些危险:当调用栈深度达到 1024 时,转账会失败(这可以被调用者强制),如果接收者没有足够的 gas,也会失败。因此,为了确保安全的以太币转账,始终检查 send 的返回值,使用 transfer 或更好的方式:使用一种模式,让接收者主动提取以太币。
3.由于 EVM 将对不存在的合约的调用视为始终成功,因此 Solidity 在执行外部调用时使用 extcodesize 操作码进行了额外检查。这确保了即将调用的合约实际上存在(它包含代码),否则会抛出异常。对地址而不是合约实例进行操作的低级调用不包括此检查(即.call()、.delegatecall()、.staticcall()、.send() 和 .transfer()),这使得它们在 gas 上更便宜,但也更不安全。

注意
1.在版本 0.5.0 之前,Solidity 允许通过合约实例访问地址成员,例如 this.balance。现在已被禁止,必须显式转换为地址:address(this).balance。
2.如果通过低级 delegatecall 访问状态变量,两个合约的存储布局必须一致,以便被调用合约能够正3.确按名称访问调用合约的存储变量。当然,如果传递存储指针作为函数参数(如高层库的情况),则存储布局不会一致。
4.在版本 0.5.0 之前,.call、.delegatecall 和 .staticcall 只返回成功状态,而不返回返回数据。
5.在版本 0.5.0 之前,有一个名为 callcode 的成员,它与 delegatecall 的语义略有不同。

8. 与合约相关

1.this (当前合约的类型):当前合约,可以显式转换为地址类型。

2.super:继承层次结构中上一级的合约。

3.selfdestruct(address payable recipient): 销毁当前合约,将其资金发送到给定的地址并结束执行。selfdestruct有一些继承自 EVM 的特性:

  • 接收合约的 receive 函数不会被执行。
  • 合约仅在交易结束时被真正销毁,并且回滚可能会“撤销”销毁操作。
  • 此外,当前合约的所有函数都可以直接调用,包括当前函数。

警告
1.从 EVM >= Cancun 开始,selfdestruct 将只会将账户中的所有以太币发送到给定的接收者,而不再销毁合约。然而,当 selfdestruct 在同一交易中被调用,并且创建了调用它的合约时,selfdestruct 会遵循 Cancun 硬分叉之前(即 EVM <= Shanghai)的行为,仍然会销毁当前合约,删除所有数据,包括存储键、代码和合约本身。详情请参见 EIP-6780。
2.新的行为是全网范围的变化,影响所有部署在以太坊主网和测试网的合约。需要注意的是,这一变化取决于合约部署链的 EVM 版本,编译合约时使用的 --evm-version 设置不会影响此行为。
3.此外,selfdestruct 操作码在 Solidity 版本 0.8.18 中已被弃用,按照 EIP-6049 的建议,弃用仍然有效,编译器会在使用时发出警告。在新部署的合约中强烈不建议使用,即使考虑到新的行为,未来 EVM 的更改可能会进一步减少该操作码的功能。

注意
在0.5.0版本之前,有一个名为suicide的函数,语义与selfdestruct相同。

9. 类型信息

表达式 type(X) 可用于检索关于类型 X 的信息。目前,支持此功能的类型有限(X 可以是合约类型或整数类型),但未来可能会扩展。

对于合约类型 C,以下属性可用:

  • type©.name:合约的名称

  • type©.creationCode:包含合约创建字节码的内存字节数组。可以在内联汇编中使用此字节码构建自定义创建例程,特别是通过使用 create2 操作码。该属性无法在合约本身或任何派生合约中访问,它会导致字节码被包含在调用站点的字节码中,因此像这样的循环引用是不可行的。

  • type©.runtimeCode:包含合约运行时字节码的内存字节数组。通常,这是合约 C 的构造函数部署的代码。如果 C 的构造函数使用了内联汇编,这可能与实际部署的字节码不同。还要注意,库在部署时会修改其运行时字节码,以防止常规调用。与 .creationCode 相同的限制也适用于此属性。

除了上述属性,以下属性适用于接口类型 I:

  • type(I).interfaceId:一个 bytes4 值,包含给定接口 I 的 EIP-165 接口标识符。此标识符是接口中所有函数选择器的 XOR,排除了所有继承的函数。

对于整数类型 T,以下属性可用:

  • type(T).min:类型 T 可表示的最小值。

  • type(T).max:类型 T 可表示的最大值。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言:指针数组、函数、二级指针

1.指针数组 指针数组是一个数组&#xff0c;数组中的每个元素都是指针。这些指针可以指向各种类型的数据&#xff0c;如整数、字符、结构体等&#xff0c;甚至可以指向其他数组或函数。 指针数组的声明格式通常为&#xff1a; 数据类型 *数组名[数组大小];其中&#xff0c;数…

批量修改记事本文本文件编码,可以解决文本文件乱码问题

对于文本文件来说&#xff0c;通常都可以设置不同的编码格式&#xff0c;每一种不同的编码格式支持的字符都可能是不一样的。因此当编码格式出现错误的时候&#xff0c;文本文件可能会出现乱码的问题。如何将文本文件的编码由一种格式变为另外一种格式呢&#xff1f;如果文件出…

亚马逊云科技提供完全托管的DeepSeek-R1模型

近日&#xff0c;亚马逊云科技宣布在Amazon Bedrock上线完全托管的DeepSeek-R1模型。DeepSeek是首个登陆Amazon Bedrock的国产大模型&#xff0c;自今年1月底推出以来&#xff0c;已有数千客户使用Amazon Bedrock的自定义模型导入功能部署了DeepSeek-R1模型。 DeepSeek在过去几…

利用 Chrome devTools Source Override 实现JS逆向破解案例

之前讲解 Chrome 一大强势技术 override 时&#xff0c;给的案例貌似没有给大家留下多深的印象 浏览器本地替换&#xff08;local overrides&#xff09;快速定位前端样式问题的案例详解&#xff08;也是hook js的手段&#xff09;_浏览器的 overrides 替换功能-CSDN博客 其实…

容器C++ ——STL常用容器

string容器 string构造函数 #include<iostream> using namespace std; #include<string.h> void test01() {string s1;//默认构造const char* str "hello world";string s2(str);//传入char*cout << "s2" << s2 << endl;s…

npu踩坑记录

之前使用qwen系列模型在ascend 910a卡进行了一些生成任务, 贴出踩坑过程也许对遇到类似问题的同学有帮助: ) 目录 千问 qwq32环境配置 代码部署 生成内容清洗 已生成内容清洗 生成过程优化 Failed to initialize the HCCP process问题 assistant 的历史回答丢失 推理执…

Linux信号——信号的产生(1)

注&#xff1a;信号vs信号量&#xff1a;两者没有任何关系&#xff01; 信号是什么&#xff1f; Linux系统提供的&#xff0c;让用户&#xff08;进程&#xff09;给其他进程发送异步信息的一种方式。 进程看待信号的方式&#xff1a; 1.信号在没有发生的时候&#xff0c;进…

【机器学习】——机器学习思考总结

摘要 这篇文章深入探讨了机器学习中的数据相关问题&#xff0c;重点分析了神经网络&#xff08;DNN&#xff09;的学习机制&#xff0c;包括层级特征提取、非线性激活函数、反向传播和梯度下降等关键机制。同时&#xff0c;文章还讨论了数据集大小的标准、机器学习训练数据量的…

JMeter进行分布式压测

从机&#xff1a; 1、确认防火墙是否关闭&#xff1b; 2、打开网络设置&#xff0c;关闭多余端口&#xff1b;&#xff08;避免远程访问不到&#xff09; 3、打开JMeter/bin 目录底下的jmeter.properties&#xff1b; remove_hosts设置当前访问地址&#xff0c;192.XXXXX&…

快速入手-基于Django-rest-framework的第三方认证插件(SimpleJWT)权限认证扩展返回用户等其他信息(十一)

1、修改serializer.py&#xff0c;增加自定义类 # 自定义用户登录token等返回信息 class MyTokenObtainPair(TokenObtainPairView): def post(self, request, *args, **kwargs): serializer self.get_serializer(datarequest.data) try: serializer.is_valid(raise_exceptio…

关于IP免实名的那些事

IP技术已成为个人与企业保护隐私、提升网络效率的重要工具。其核心原理是通过中介服务器转发用户请求&#xff0c;隐藏真实IP地址&#xff0c;从而实现匿名访问、突破地域限制等目标。而“免实名”代理IP的出现&#xff0c;进一步简化了使用流程&#xff0c;用户无需提交身份信…

【SQL性能优化】预编译SQL:从注入防御到性能飞跃

&#x1f525; 开篇&#xff1a;直面SQL的"阿喀琉斯之踵" 假设你正在开发电商系统&#x1f6d2;&#xff0c;当用户搜索商品时&#xff1a; -- 普通SQL拼接&#xff08;危险&#xff01;&#xff09; String sql "SELECT * FROM products WHERE name "…

SQL Server从安装到入门一文掌握应用能力。

本篇文章主要讲解,SQL Server的安装教程及入门使用的基础知识,通过本篇文章你可以快速掌握SQL Server的建库、建表、增加、查询、删除、修改等基本数据库操作能力。 作者:任聪聪 日期:2025年3月31日 一、SQL Server 介绍: SQL Server 是微软旗下的一款主流且优质的数据库…

力扣HOT100之矩阵:54. 螺旋矩阵

这道题之前在代码随想录里刷过类似的&#xff0c;还有印象&#xff0c;我就按照当初代码随想录的思路做了一下&#xff0c;结果怎么都做不对&#xff0c;因为按照代码随想录的边界条件设置&#xff0c;当行数和列数都为奇数时&#xff0c;最后一个元素无法被添加到数组中&#…

5.1 WPF路由事件以及文本样式

一、路由事件 WPF中存在一种路由事件&#xff08;routed event&#xff09;&#xff0c;该事件将发送到包含该控件所在层次的所有控件&#xff0c;如果不希望继续向更高的方向传递&#xff0c;只要设置e.Handled true即可。 这种从本控件-->父控件->父的父控件的事件&am…

Python数据可视化-第1章-数据可视化与matplotlib

环境 开发工具 VSCode库的版本 numpy1.26.4 matplotlib3.10.1 ipympl0.9.7教材 本书为《Python数据可视化》一书的配套内容&#xff0c;本章为第1章 数据可视化与matplotlib 本文主要介绍了什么是数据集可视化&#xff0c;数据可视化的目的&#xff0c;常见的数据可视化方式…

Flutter敏感词过滤实战:基于AC自动机的高效解决方案

Flutter敏感词过滤实战&#xff1a;基于AC自动机的高效解决方案 在社交、直播、论坛等UGC场景中&#xff0c;敏感词过滤是保障平台安全的关键防线。本文将深入解析基于AC自动机的Flutter敏感词过滤实现方案&#xff0c;通过原理剖析实战代码性能对比&#xff0c;带你打造毫秒级…

Odoo/OpenERP 和 psql 命令行的快速参考总结

Odoo/OpenERP 和 psql 命令行的快速参考总结 psql 命令行选项 选项意义-a从脚本中响应所有输入-A取消表数据输出的对齐模式-c <查询>仅运行一个简单的查询&#xff0c;然后退出-d <数据库名>指定连接的数据库名&#xff08;默认为当前登录用户名&#xff09;-e回显…

Vue中使用antd-table组件时,树形表格展开配置不生效-defaultExpandedRowKeys-默认展开配置不生效

defaultExpandedRowKeys属性 defaultExpandAllRows这个属性仅仅是用来设置默认值的,只在第一次渲染的时候起作用,后续再去改变,无法实现响应式 解决方案一 a-table表格添加key属性,当每次获取值时,动态改变key,以达到重新渲染的效果 <a-table:key="tableKey"…

VRRP交换机三层架构综合实验

题目要求&#xff1a; 1&#xff0c;内网Ip地址使用172.16.0.0/16分配 说明可以划分多个子网&#xff0c;图中有2个VLAN&#xff0c;可以根据VLAN划分 2&#xff0c;sw1和SW2之间互为备份 互为备份通常通过VRRP&#xff08;虚拟路由冗余协议&#xff09;来实现。VRRP会在两个…