【區塊鏈安全 | 第十四篇】類型之值類型(一)

文章目錄

  • 值類型
    • 布爾值
    • 整數
      • 運算符
      • 取模運算
      • 指數運算
    • 定點數
    • 地址(Address)
      • 類型轉換
      • 地址成員
        • balance 和 transfer
        • send
        • call,delegatecall 和 staticcall
        • code 和 codehash
    • 合約類型(Contract Types)
    • 固定大小字節數組(Fixed-size byte arrays)
    • 地址字面量(Address Literals)

在這里插入圖片描述

Solidity 是一種靜態類型語言,這意味著每個變量(無論是狀態變量還是局部變量)都需要指定其類型。Solidity 提供了幾種基本類型,這些類型可以組合形成復雜類型。

此外,不同類型可以在包含運算符的表達式中相互作用,并且具有優先級的區分。

Solidity 沒有“未定義”或“空”值的概念,但新聲明的變量總是具有默認值,該默認值取決于其類型。為了處理任何意外的值,應該使用 revert 函數回滾整個交易,或者返回一個帶有布爾值的元組,其中第二個 bool 值表示操作是否成功。

值類型

值類型的變量始終按值傳遞,即在作為函數參數或賦值時總是被復制。

與引用類型不同,值類型的聲明不指定數據位置,因為它們足夠小,可以存儲在棧中。唯一的例外是狀態變量,狀態變量默認存儲在存儲中,但也可以標記為 transient、constant 或 immutable。

布爾值

bool:值是 truefalse

整數

int / uint:各種大小的有符號和無符號整數。

關鍵字 uint8uint256(以 8 為步長,表示 8 位到 256 位的無符號整數),以及 int8int256

uintint 分別是 uint256int256 的別名。

運算符

比較運算符:<=<==!=>=>(結果為 bool

位運算符:&|^(按位異或),~(按位取反)

移位運算符:<<(左移),>>(右移)

算術運算符:+-,一元 -(僅適用于有符號整數),*/%(取模),**(指數運算)

對于整數類型 X,可以使用 type(X).mintype(X).max 來訪問該類型可表示的最小值和最大值。

運算符 ||&& 遵循短路規則。這意味著在表達式 f(x) || g(y) 中,如果 f(x) 計算結果為 true,則 g(y) 將不會被計算。

注意
Solidity 中的整數受到特定范圍的限制。例如,對于 uint32,其范圍為 02**32 - 1

在 Solidity 中,整數運算有兩種模式:“溢出”模式(wrapping/unchecked mode)“檢查”模式(checked mode)

默認情況下,運算始終處于 “檢查”模式,這意味著如果運算結果超出了類型的值范圍,則調用會因失敗的斷言而回滾。

可以使用 unchecked { ... } 切換到 “溢出”模式,但應謹慎使用。

取模運算

% 的結果是操作數 a 除以操作數 n 后的余數 r,其中 q = int(a / n),并且 r = a - (n * q)

這意味著取模運算的結果與其左操作數的符號相同(或為零),并且對于負數 aa % n == -(-a % n) 恒成立:

int256(5) % int256(2) == int256(1)int256(5) % int256(-2) == int256(1)int256(-5) % int256(2) == int256(-1)int256(-5) % int256(-2) == int256(-1)

注意:使用 0 作為取模運算的除數會導致 Panic 錯誤。此檢查無法通過 unchecked { ... } 關閉。

指數運算

指數運算 ** 僅適用于無符號類型作為指數(冪)。指數運算的結果類型始終與底數的類型相同。請確保底數足夠大以容納結果,并預防潛在的斷言失敗或溢出行為。

注意:在 檢查模式(checked mode)下,對于較小的底數,指數運算僅使用相對廉價的 EXP 操作碼。

例如,在計算 x**3 時,使用 x*x*x 可能更便宜。因此,建議進行 Gas 成本測試 并使用優化器。此外,EVM 規定 0**0 的結果為 1

定點數

警告:定點數在 Solidity 中尚不完全支持。它們可以被聲明,但不能進行賦值操作。

fixed / ufixed:帶符號和無符號定點數,具有不同的大小。關鍵字 ufixedMxNfixedMxN,其中 M 代表類型所占用的位數,N 代表可用的小數位數。M 必須是 8 的倍數,范圍從 8 到 256 位。N 必須在 0 到 80 之間(包含 0 和 80)。ufixedfixedufixed128x18fixed128x18 的別名。

操作符

  • 比較操作符:<=<==!=>=>(結果為布爾值)

  • 算術操作符:+-,一元 -(僅對帶符號數),*/%(取模)

注意:浮動點數(許多語言中的 floatdouble,更精確地說是 IEEE 754 數字)和定點數的主要區別在于,浮動點數用于表示整數和小數部分的位數是靈活的,而定點數則嚴格定義了每部分所占的位數。通常,在浮動點數中,幾乎整個空間用于表示數字,而只有少數位數用于定義小數點的位置。

地址(Address)

地址類型有兩種主要相似的變體:

  • address:持有一個 20 字節的值(以太坊地址的大小)。
  • address payable:與 address 相同,但具有額外的 transfersend 成員。

這種區分的想法是,address payable 是一個可以接收以太幣的地址,而普通的 address 不能接收以太幣,例如,它可能是一個不支持接收以太幣的智能合約。

類型轉換

1.允許從 address payableaddress 的隱式轉換,而從 addressaddress payable 必須通過顯式轉換 payable(<address>)
2.允許顯式轉換到 address 類型并返回 uint160、整數字面量、bytes20 和合約類型。
3.只有 address 類型和合約類型的表達式可以通過顯式轉換 payable(...) 轉換為 address payable。對于合約類型,只有在合約可以接收以太幣的情況下(即合約有 receivepayable 回退函數)才能進行這種轉換。注意,payable(0) 是有效的,且是這一規則的例外。

注意
如果我們需要一個 address 類型的變量,并計劃向其發送以太幣,那么應將其聲明為 address payable 以使該要求更加明顯。此外,盡量在最早階段做出這種區分或轉換。

從 0.5.0 版本開始,addressaddress payable 之間的區分被引入。自那時起,合約不能隱式轉換為 address 類型,但如果它們有 receivepayable 回退函數,仍然可以顯式地轉換為 addressaddress payable

地址成員

balance 和 transfer

可以使用 balance 屬性查詢地址的余額,并使用 transfer 函數將以太幣(以 wei 為單位)發送到可支付的地址:

address payable x = payable(0x123);
address myAddress = address(this);
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);

transfer 函數在當前合約的余額不足或接收方帳戶拒絕接收以太幣時失敗,并會回滾操作。

注意
如果 x 是一個合約地址,它的代碼(更具體地說:其 Receive Ether 函數如果存在,或其他回退函數如果存在)將在 transfer 調用時一起執行,這是 EVM 的特性,無法阻止。如果該執行耗盡了 gas 或以任何方式失敗,Ether 轉賬將回滾,當前合約將停止并拋出異常。

send

sendtransfer 的低級對等函數。如果執行失敗,當前合約不會停止并拋出異常,而是返回 false

使用 send 時存在一些危險:如果調用堆棧深度達到 1024(調用者可以強制此情況),或者接收方耗盡 gas,則轉賬將失敗。因此,為了安全地轉賬以太幣,始終檢查 send 的返回值,使用 transfer 或更好的方式是使用一個模式,其中接收方自己提取以太幣。

call,delegatecall 和 staticcall

為了與不符合 ABI 的合約交互,或為了更直接地控制編碼,可以使用 calldelegatecallstaticcall 函數。它們都接受一個字節內存參數,并返回成功條件(布爾值)和返回的數據(字節內存)。abi.encodeabi.encodePackedabi.encodeWithSelectorabi.encodeWithSignature 可以用來編碼結構化數據。

示例:

bytes memory payload = abi.encodeWithSignature("register(string)", "MyName");
(bool success, bytes memory returnData) = address(nameReg).call(payload);
require(success);

注意,這些都是低級函數,應該小心使用。特別是,任何未知的合約可能是惡意的,如果調用它,你將把控制權交給該合約,而該合約可能會再次調用你的合約,因此當調用返回時,需要做好準備處理可能會更改的狀態變量。與其他合約交互的常規方式是調用合約對象上的函數(例如 x.f())。

可以使用 gas 修飾符調整提供的 gas:

address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName"));

類似地,也可以控制提供的 Ether 數量:

address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName"));

最后,這些修飾符可以結合使用,它們的順序無關緊要:

address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName"));

類似地,可以使用 delegatecall 函數,不同之處在于,只有給定地址的代碼會被使用,所有其他方面(存儲、余額等)都來自當前合約。delegatecall 的目的是使用存儲在另一個合約中的庫代碼。用戶必須確保兩個合約的存儲布局適合使用 delegatecall

code 和 codehash

你可以查詢任何智能合約的已部署代碼。使用 .code 獲取 EVM 字節碼作為字節內存(可能為空)。使用 .codehash 獲取該代碼的 Keccak-256 哈希(作為 bytes32)。注意,addr.codehash 比使用 keccak256(addr.code) 更便宜。

如果與 addr 相關聯的帳戶為空或不存在(即它沒有代碼、零余額和零 nonce,如 EIP-161 所定義),則 addr.codehash 的輸出可能為 0。如果該帳戶沒有代碼,但有非零余額或 nonce,則 addr.codehash 將輸出空數據的 Keccak-256 哈希(即 keccak256(""),其結果為 c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470)。

注意,所有合約都可以轉換為 address 類型,因此可以使用 address(this).balance 查詢當前合約的余額。

合約類型(Contract Types)

每個合約都定義了自己的類型。你可以將合約隱式轉換為它繼承的合約類型。合約類型可以顯式地轉換為 address 類型,反之亦然。

顯式轉換到 address payable 類型僅在合約類型有 receivepayable 回退函數時才可能。轉換仍然通過 address(x) 進行。如果合約類型沒有 receivepayable 回退函數,可以使用 payable(address(x)) 進行轉換。

注意
1.如果你聲明一個合約類型的局部變量(例如 MyContract c),你可以在該合約上調用函數。需要注意的是,必須從與之相同的合約類型賦值給該變量。
2.你也可以實例化合約(這意味著它們是新創建的)。你可以在“通過 new 創建合約”部分找到更多的細節。
3.合約的數據顯示方式與 address 類型相同,并且這種類型也用于 ABI 中。
4.合約不支持任何操作符。
5.合約類型的成員是該合約的外部函數,包括任何標記為 public 的狀態變量。
6.對于合約 C,你可以使用 type(C) 來訪問有關該合約的類型信息。

固定大小字節數組(Fixed-size byte arrays)

值類型 bytes1, bytes2, bytes3, …, bytes32 用于存儲從 1 到 32 字節的字節序列。

操作符:

  • 比較操作符:<=, <, ==, !=, >=, >(返回布爾值)
  • 位操作符:&, |, ^(按位異或),~(按位取反)
  • 移位操作符:<<(左移),>>(右移)
  • 索引訪問:如果 x 是類型 bytesI,則 x[k](0 <= k < I)返回第 k 個字節(只讀)。

移位操作符與無符號整數類型作為右操作數一起工作(但返回左操作數的類型),表示要移位的位數。使用有符號類型進行移位會導致編譯錯誤。

成員.length 可以返回字節數組的固定長度(只讀)。

注意
類型 bytes1[] 是字節的數組,但由于填充規則,對于每個元素,它浪費 31 字節的空間(在存儲中除外)。最好使用 bytes 類型。

地址字面量(Address Literals)

地址字面量是通過地址校驗和測試的十六進制字面量,例如 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AFaddress 類型。長度在 39 到 41 位之間且未通過校驗和測試的十六進制字面量會產生錯誤。

我們可以通過在前面(對于整數類型)或后面(對于 bytesNN 類型)加零來去除錯誤。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75286.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75286.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75286.shtml

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

相關文章

Windows 系統下多功能免費 PDF 編輯工具詳解

IceCream PDF Editor是一款極為實用且操作簡便的PDF文件編輯工具&#xff0c;它完美適配Windows操作系統。其用戶界面設計得十分直觀&#xff0c;哪怕是初次接觸的用戶也能快速上手。更為重要的是&#xff0c;該軟件具備豐富多樣的強大功能&#xff0c;能全方位滿足各類PDF編輯…

vue3相比于vue2的提升

性能提升&#xff1a; Vue3的頁面渲染速度更快、性能更好。特別是在處理大量數據和復雜組件時&#xff0c;優勢更加明顯。Vue3引入了編譯時優化&#xff0c;如靜態節點提升&#xff08;hoistStatic&#xff09;、補丁標志&#xff08;patchflag&#xff09;等&#xff0c;這些…

Redis 梳理匯總目錄

Redis 哨兵集群&#xff08;Sentinel&#xff09;與 Cluster 集群對比-CSDN博客 如何快速將大規模數據保存到Redis集群-CSDN博客 Redis的一些高級指令-CSDN博客 Redis 篇-CSDN博客

【奇點時刻】GPT-4o新生圖特性深度洞察報告

以下報告圍繞最新推出的「GPT4o」最新圖像生成技術展開&#xff0c;旨在讓讀者從整體層面快速了解其技術原理、功能亮點&#xff0c;以及與其他常見圖像生成或AI工具的對比分析&#xff0c;同時也會客觀探討該技術在應用過程中可能遇到的挑戰與限制。 1. 技術背景概述 GPT4o新…

【算法day28】解數獨——編寫一個程序,通過填充空格來解決數獨問題

37. 解數獨 編寫一個程序&#xff0c;通過填充空格來解決數獨問題。 數獨的解法需 遵循如下規則&#xff1a; 數字 1-9 在每一行只能出現一次。 數字 1-9 在每一列只能出現一次。 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。&#xff08;請參考示例圖&#xff…

【已解決】Javascript setMonth跨月問題;2025-03-31 setMonth后變成 2025-05-01

文章目錄 bug重現解決方法&#xff1a;用第三方插件來實現&#xff08;不推薦原生代碼來實現&#xff09;。項目中用的有dayjs。若要自己實現&#xff0c;參考 AI給出方案&#xff1a; bug重現 今天&#xff08;2025-04-01&#xff09;遇到的一個問題。原代碼邏輯大概是這樣的…

力扣刷題-熱題100題-第29題(c++、python)

19. 刪除鏈表的倒數第 N 個結點 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/?envTypestudy-plan-v2&envIdtop-100-liked 計算鏈表長度 對于鏈表&#xff0c;難的就是不知道有多少元素&#xff…

【QT】QT的多界面跳轉以及界面之間傳遞參數

QT的多界面跳轉以及界面之間傳遞參數 一、在QT工程中添加新的界面二、多界面跳轉的兩種情況1、A界面跳到B界面&#xff0c;不需要返回2、A界面跳到B界面&#xff0c;需要返回1&#xff09;使用this指針傳遞將當前界面地址傳遞給下一界面2&#xff09;使用parentWidget函數獲取上…

【力扣hot100題】(022)反轉鏈表

非常經典&#xff0c;我寫的比較復雜&#xff0c;一直以來的思路都是這樣&#xff0c;就沒有去找更簡單的解法&#xff1a;&#xff08;做鏈表題習慣加頭結點的前置節點了&#xff0c;去掉也行&#xff09; /*** Definition for singly-linked list.* struct ListNode {* …

劍指Offer(數據結構與算法面試題精講)C++版——day2

劍指Offer(數據結構與算法面試題精講)C++版——day2 題目一:只出現一次的數據題目二:單詞長度的最大乘積題目三:排序數組中的兩個數字之和題目一:只出現一次的數據 一種很簡單的思路是,使用數組存儲出現過的元素,比如如果0出現過,那么arr[0]=1,但是有個問題,題目中沒…

【C++游戲引擎開發】《線性代數》(3):矩陣乘法的SIMD優化與轉置加速

一、矩陣乘法數學原理與性能瓶頸 1.1 數學原理 矩陣乘法定義為:給定兩個矩陣 A ( m n ) \mathrm{A}(mn) A(mn)和 B ( n p ) \mathrm{B}(np) B(np),它們的乘積 C = A B \mathrm{C}=AB C=AB 是一個 m p \mathrm{m}p mp 的矩陣,其中: C i , j = ∑ k = 1…

Vue Transition組件類名+TailwindCSS

#本文教學結合TailwindCSS實現一個Transition動畫的例子# 舉例代碼&#xff1a; <transition enter-active-class"transition-all duration-300 ease-out"enter-from-class"opacity-0 translate-y-[-10px]"enter-to-class"opacity-100 translate-…

技術回顧day2

1.獲取文件列表 流程&#xff1a;前端根據查詢條件封裝查詢信息&#xff0c;后端接收后進行封裝&#xff0c;封裝為FileInfoQuery,根據fileInfoQuery使用mybatis的動態sql來進行查詢。 2.文件分片上傳 每次上傳需要上傳包括(文件名字&#xff0c;文件&#xff0c;md5值&#…

DeepSeek-R1 模型現已在亞馬遜云科技上提供

2025年3月10日更新—DeepSeek-R1現已作為完全托管的無服務器模型在Amazon Bedrock上提供。 2025年2月5日更新—DeepSeek-R1 Distill Llama 和 Qwen模型現已在Amazon Bedrock Marketplace和Amazon SageMaker JumpStart中提供。 在最近的Amazon re:Invent大會上&#xff0c;亞馬…

STP --- 生成樹協議

協議信息 配置 BPDU Protocol identifier&#xff1a;協議標識 Version&#xff1a;協議版本&#xff1a;STP 為 0&#xff0c;RSTP 為 2&#xff0c;MSTP 為 3 type&#xff1a; BPDU 類型 Flag&#xff1a; 標志位 Root ID&#xff1a; 根橋 ID&#xff0c;由兩字節的優…

Ansible playbook-ansible劇本

一.playbook介紹 便于功能的重復使用 本質上就是文本文件&#xff0c;一般都是以.yml結尾的文本文件。 1.遵循YAML語法 1.要求同級別代碼要有相同縮進&#xff0c;建議4個空格。【同級別代碼是同一邏輯的代碼】 在計算機看來空格和Tob鍵是兩個不同的字符。 2.一個鍵對應一…

python的基礎入門

初識Python 什么是Python Python是1門程序設計語言。在開發者眼里&#xff0c;語言可以分為3類&#xff1a; 自然語言&#xff1a;人能聽懂的語言&#xff0c;例如漢語&#xff0c;英語&#xff0c;法語等等。機器語言&#xff1a;機器能聽懂的語言&#xff0c;機器只能聽懂0…

MD編輯器中的段落縮進怎么操作

在 Markdown&#xff08;MD&#xff09;編輯器中&#xff0c;段落的縮進通常可以通過 HTML 空格符、Markdown 列表縮進、代碼塊縮進等方式 實現。以下是幾種常見的段落縮進方法&#xff1a; 1. 使用全角空格 ( ) 在一些 Markdown 編輯器&#xff08;如 Typora&#xff09;中&…

8.neo4j圖數據庫python操作

使用圖數據庫的原因 圖數據庫使用neo4j的原因&#xff1a;neo4j使用率高&#xff0c;模板好找&#xff0c;報錯能查。 紅樓夢人物關系圖地址 GraphNavigator neo4j學習手冊 https://www.w3cschool.cn/neo4j/neo4j_need_for_graph_databses.html CQL代表的是Cypher查詢語言…

[Lc6_記憶化搜索] 掃雷游戲 | 理解 遞歸vs記憶化搜索vs dp

目錄 ?1.掃雷游戲 題解 1.記憶化搜索 解法一&#xff1a;遞歸 解法二&#xff1a;記憶化搜索 解法三&#xff1a;動態規劃 ?1.掃雷游戲 (暴力模擬&#xff09; 鏈接&#xff1a;529. 掃雷游戲 讓我們一起來玩掃雷游戲&#xff01; 給你一個大小為 m x n 二維字符矩陣…