【區塊鏈安全 | 第二十四篇】單位和全局可用變量(二)

文章目錄

  • 單位和全局可用變量(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.pswp.cn/web/74156.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74156.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74156.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一種監控錄像視頻恢復的高效解決方案,從每一幀中尋找可能性

該軟件旨在恢復從監控設備中刪除或丟失的視頻。該程序經過調整以處理大多數流行供應商的閉路電視系統中使用的專有格式&#xff0c;并通過智能重建引擎進行了增強&#xff0c;能夠為監控記錄提供任何通用解決方案都無法實現的恢復結果。如果不需要持續使用該軟件&#xff0c;則…

網紅指路機器人是否支持環境監測功能?

嘿呀&#xff0c;你可知道&#xff1f;如今的叁仟網紅指路機器人那可太牛啦&#xff01;它們可不單單局限于為行人指明方向&#xff0c;還紛紛兼職當起了 “環境小衛士”&#xff0c;為咱們的城市生活注入了前所未有的超智能便利。就拿那個依托叁仟智慧桿打造的數智指路機器人來…

Navicat導出mysql數據庫表結構說明到excel、word,單表導出方式記錄

目前只找到一張一張表導出的方式 使用information_schema傳入表名查詢 字段名根據需要自行刪減&#xff0c;一般保留序號、字段名、類型、說明就行 SELECT COLUMNS.ORDINAL_POSITION AS 序號, COLUMNS.COLUMN_NAME AS 字段名, COLUMNS.COLUMN_TYPE AS 類型(長度), COLUMNS.N…

MySQL主從數據庫搭建

此方案可適用于Centos 7、OpenEuler、Ubuntu操作系統。 在國產銀河麒麟V10中,虛擬機中啟動的麒麟系統使用當前方案并未遇到問題,但是在服務器上安裝時,執行到初始化時出現了找不到依賴問題(目前已解決安裝問題),后續我會繼續更新該問題解決方案。 1. 創建主、從安裝目錄…

`git commit --amend` 詳解:修改提交記錄的正確方式

文章目錄 git commit --amend 詳解&#xff1a;修改提交記錄的正確方式1. 修改提交信息2. 補充遺漏的文件3. 結合 --amend 進行交互式修改4. 已推送提交的修改總結 git commit --amend 詳解&#xff1a;修改提交記錄的正確方式 git commit --amend 用于修改最近一次的提交&…

為什么package.json里的npm和npm -v版本不一致?

這個情況出現是因為package.json里的 npm 版本和系統實際使用的 npm 版本是兩個不同的概念。讓我來解釋一下&#xff1a; 原因解釋 全局 npm vs 項目依賴&#xff1a; npm -v顯示的是系統全局安裝的 npm 版本&#xff08;位于/usr/bin/npm或類似路徑&#xff09;package.jso…

python系統之綜合案例:用python打造智能詩詞生成助手

不為失敗找理由&#xff0c;只為成功找方法。所有的不甘&#xff0c;因為還心存夢想&#xff0c;所以在你放棄之前&#xff0c;好好拼一把&#xff0c;只怕心老&#xff0c;不怕路長。 python系列之綜合案例 前言一、項目描述二、項目需求三、 項目實現1、開發準備2、代碼實現 …

Java常用工具算法-1--哈希算法(MD5,SHA家族,SHA-256,BLAKE2)

1、概述 哈希算法&#xff08;Hash Algorithm&#xff09;&#xff0c;又稱散列算法&#xff0c;是一種將任意長度的輸入數據&#xff08;明文&#xff09;轉換為固定長度的輸出&#xff08;哈希值/摘要&#xff09;的數學算法。 哈希值通常被稱為摘要&#xff08;Digest&…

OpenMCU(五):STM32F103時鐘樹初始化分析

概述 本文主要描述了STM32F103初始化過程系統時鐘的初始化,主要描述了系統時鐘的初始化&#xff0c;AHB總線時鐘&#xff0c;APB總線時鐘等的初始化。 硬件板卡3d圖 時鐘樹 STM32F103的時鐘樹&#xff0c;如下所示: 時鐘源選擇 從STM32F103的時鐘樹框圖&#xff0c;我們可以…

【qt】文件類(QFile)

很高興你能看到這篇文章&#xff0c;同時我的語雀文檔也更新了許多嵌入式系列的學習筆記希望能幫到你 &#xff1a; https://www.yuque.com/alive-m4b9n 目錄 QFile 主要功能QFile 操作步驟QFile 其他常用函數案例分析及實現功能一實現&#xff1a;打開文件并顯示功能二實現:另…

基于AT89C52單片機的輪胎壓力監測系統

點擊鏈接獲取Keil源碼與Project Backups仿真圖&#xff1a; https://download.csdn.net/download/qq_64505944/90545655?spm1001.2014.3001.5503 功能介紹&#xff1a; 采用MPX4115壓力傳感器進行輪胎壓力檢測&#xff1b;使用LCD液晶顯示器顯示輪胎壓力&#xff1b;若壓力過…

shell腳本--MySQL簡單調用

實現功能 增 數據庫的創建&#xff0c;數據表的創建已經實現 創建用戶 刪 刪除數據庫&#xff0c; 刪除庫下的某個表&#xff0c; 刪除某個用戶 改 暫無 查 查看所有的數據庫&#xff0c; 查看某個庫下的所有數據表&#xff0c; 查看某個表的結構&#xff0c; 查…

計算機網絡 OSI參考模型

目錄 OSS七層 OSI通信過程1 OSI通信過程2 應用層 表示層 會話層 傳輸層 網絡層 數據鏈路層 物理層 OSS七層 OSI通信過程1 OSI通信過程2 應用層 表示層 會話層 傳輸層 網絡層 數據鏈路層 物理層

2025年華為HCIP題庫分享

1101、 【拖拽題】OPSF鄰接關系建立的過程中需要使用不同的報文&#xff0c;那么請分別將以下各個狀態和該狀態使用的報文聯系起來。 答題格式為&#xff1a;11 22 33 43 正確答案&#xff1a;【12】【21】【24】【33】 解析&#xff1a; 建立鄰居關系 RouterA的一個連接到廣…

DIskgenius使用說明

文章目錄 一、概述1. 軟件簡介2. 系統要求 二、核心功能1. 分區管理(1) 查看磁盤分區(2) 創建與刪除分區(3) 調整分區大小(4) 格式化分區 2. 數據恢復(1) 恢復已刪除文件(2) 恢復丟失分區(3) 恢復誤格式化分區 3. 磁盤復制(1) 克隆磁盤(2) 磁盤鏡像 4. 文件操作(1) 文件復制與移…

linux--------------進程控制(上)

1.進程創建 1.1fork函數初識 在linux中fork函數是?常重要的函數&#xff0c;它從已存在進程中創建?個新進程。新進程為?進程&#xff0c;?原進 程為?進程。 #include <unistd.h> pid_t fork(void); 返回值&#xff1a;?進程中返回0&#xff0c;?進程返回?進程id…

windows免密SSH連接 ubuntu教程

文章目錄 前情提要step1. 在windows下生成SSH密鑰step2. SSH公鑰copy到ubuntu的~/.ssh/authorized_keys內step3. 修改文件權限&#xff08;這一步完成后就可以實現免密SSH連接了&#xff09; 前情提要 ubuntu下安裝SSH服務 sudo apt-get install openssh-serverwindows下安裝…

中級:數組算法面試題全解析

一、引言 在Java面試中&#xff0c;數組相關的算法題是考察候選人基礎算法能力的常見類型。面試官通過這些問題了解候選人在面對具體問題時的邏輯思維和代碼實現能力。本文將深入剖析常見的數組算法面試題&#xff0c;結合實際開發場景&#xff0c;幫助讀者全面掌握這些知識點…

《Linux運維實戰:Ubuntu 22.04配置pam實現密碼復雜度策略》

總結&#xff1a;整理不易&#xff0c;如果對你有幫助&#xff0c;可否點贊關注一下&#xff1f; 更多詳細內容請參考&#xff1a;Linux運維實戰總結 一、背景信息 由于安全方面的考慮&#xff0c;先要求Ubuntu 22.04系統需配置密碼復雜度策略&#xff0c;先要求如下&#xff1…

JavaScript數據結構

目錄 JavaScript數據結構 一、基礎數據結構 1. 數組&#xff08;Array&#xff09; 2. 對象&#xff08;Object&#xff09; 二、ES6 高級數據結構 1. Map 2. Set 3. WeakMap 與 WeakSet 三、類型化數組&#xff08;Typed Arrays&#xff09; 四、其他數據結構實現 …